6

だからここに私が知っていることがあります:

  • API で ivar を直接公開しないことが賢明です。むしろ、アクセサーを使用してください
  • constconstオブジェクトへのポインターは、単にオブジェクトを変更できることを意味しますが、ポインターが指す場所をリダイレクトすることはできません

これが私の状況です:

関連するクラスがいくつかあります。私は、合成を介してこれらを 1 つの論理インターフェイスに結合する単純なクラスを作成したいと考えています。囲まれた各クラスは、その API でパブリックとプライベートの区別が既にあるため、親クラスのユーザーに直接公開してもかまいません。これは、これらの ivar のアクセサーを作成するのはやり過ぎであることを意味します。なぜなら、クラスは既に公開されているものと公開されていないものを管理しているからです。しかし、この構成された親クラスに含まれる実際のオブジェクトをユーザーが変更することは望ましくありません。

したがって、これを行うために考えることができる唯一の方法はconst、これらのオブジェクトへのポインターを使用することです。

class Parent{

  public:

   EnclosedClass1*const ec1; //users can enjoy the public API of EnclosedClass
   EnclosedClass2*const ec2;

   void convenienceMethod(){
         //performs inter-related functions on both ec1 and ec2
    }

 }

ec1このように、誰かがandの API と直接やり取りしても害はありませんが、少なくともその人が操作される実際のリソース、したがってポインターec2を変更できないという点で、これがかなり確実であることを確認したいと思います。const

これは理にかなっていますか、それは const ポインターの適切な使用ですか?

別の方法として、それらをprivate完全に作成し、ポインターを忘れて (このクラスはこれらのオブジェクトをとにかく管理します)、これらのオブジェクトに含まれるパブリック関数のアクセサーを記述するための余分な作業を行うこともできます。しかし、それはやり過ぎに思えますよね?

4

6 に答える 6

6

従来の OOP の方法では、データをプライベートに保ち、クラスの外で使用する場合はパブリック アクセサーを使用します。

プライベート データ ポインターを変更したくない場合は、セッターを提供せず、ゲッターのみを提供します。

class Parent{

  private:
       EnclosedClass1*const ec1;
       EnclosedClass2*const ec2;

  public:
      EnclosedClass1* getEnclosedClass1() const {...};
      EnclosedClass2* getEnclosedClass2() const {...};    

      void convenienceMethod(){
    }

}

別の可能性(@pmrが以下のコメントで提案しているように)は次のとおりです。

const EnclosedClass1& getEnclosedClass1() const {...};
const EnclosedClass2& getEnclosedClass2() const {...};    

const 参照を使用すると、ゲッターによって返された値をテストすることからユーザーを保護できます。ただし、オブジェクトの状態に一貫性があり、への内部ポインターがないようにする必要がありますnullptr。そのような場合は、例外をスローする必要があります。

于 2013-05-06T12:15:28.180 に答える
2

このアプローチにはさまざまな問題があります。1つ目は、メンバーがインターフェースに対してパブリック側とプライベート側を持っているという事実は、囲んでいる型の観点からは何の意味もないということです。完全な型には、ユーザーが 2 つのサブオブジェクトを個別に変更することで破ることができる、異なる一連の不変条件を含めることができます。

Parent型に不変条件がない (つまり、サブオブジェクトの状態に依存しない) 場合でも、提案されたアプローチは const-correct ではありません。呼び出し元が任意const Parent&の操作 (const および const ではない) を両方のサブオブジェクトに適用できる場合、Parentオブジェクトの状態を効果的に変更できます。この場合の少し良い方法は、サブオブジェクトを直接保存することです。

class Parent {
public:
   EnclosedClass1 ec1;
   EnclosedClass2 ec2;
...

ただし、データを抽出するためのアクセサーと、オブジェクトの状態を変更するためのミューテーター(意味がある場合) を提供することをお勧めします。そうすれば、後で不変条件を追加する必要がある場合でも、そこに貼り付けることができます。

于 2013-05-06T12:26:56.583 に答える
0

他の 2 つのオブジェクトを含み、それらのメンバーへの無料かつ完全なアクセスをクライアントに提供するクラスがある場合、そのクラスが適切に設計されているかどうかを検討する必要があります。getter を使用しないため、demeter の法則が無効になることはありません。つまり、parent.ec1->foo は、parent.getEc1().foo と同じです。

いずれにせよ、const メンバーは一般に、価値があるよりも問題が多くなります。

于 2013-05-06T12:18:20.813 に答える