2016-03-24 11 views
1

私はクラス(例として名前を)持っている:OOPデザイン - 保護された独自のクラスで使用されていないメンバー - だけサブクラスで使用

class Animal 
{ 
public: 
    // some virtual methods 
}; 

は、いくつかのサブクラスもあります。あなたが見ることができるように犬と象のオブジェクトを作成するときに

class Dog : public Animal 
{ 
public: 
    Dog(Map&); 
    // methods - using m_Map 
private: 
    Map& m_Map; 
}; 


class Elephant : public Animal 
{ 
public: 
    Elephant(Map&); 
    // methods - using m_Map 
private: 
    Map& m_Map; 
}; 

は、マップの参照が提供されなければならない、とこれらのクラスは、それを使用しています。 Animal(Dog、Elephant、Mouse、Catなど)の類似したサブクラスがたくさんあります - すべてMapオブジェクトを使用します。

動物のすべてのサブクラスはMapオブジェクトを使用して、私は例えば、保護されたメンバーとしてAnimalクラスに追加する良いでしょう場合を考えていた:

class Animal 
{ 
public: 
    Animal(Map&); 
    // some virtual methods 
protected: 
    Map& m_Map; 
}; 

class Dog : public Animal 
{ 
public: 
    Dog(Map& map) : Animal(map); 
    // methods - using Animal::m_Map 
}; 

class Elephant : public Animal 
{ 
public: 
    Elephant(Map& map) : Animal(map); 
    // methods - using Animal::m_Map 
}; 

しかし、Animalクラス決してMapオブジェクトを使用しているので、ここではそれを格納するのが自然ではないようです。サブクラスの使用のみです。

一方、AnimalのすべてのサブクラスはMapオブジェクトを使用します。そのため、Animalクラスで表示するとよいでしょう。また、すべてのサブクラスでメンバーとして定義すると、コードが重複していると感じています。

あなたはどう思いますか? Mapオブジェクトは、すべてのサブクラスまたはAnimalクラスのメンバとして定義する必要がありますか?

+0

外部状態への参照はデザインが小さいです。しかしそれとは別に、基本クラスの機能として共通性を捕捉​​することはOKです。これが基本クラスの目的です。 –

+0

これはプログラマのためのより良い質問です。 – xaxxon

+0

私はプログラマーズに所属しているので、この質問を議論の対象にしないと投票しています。 – xaxxon

答えて

2

これは、動物と地図の間のセマンティックリンクに依存します。

あなたはC++であるため、複数の継承を使用できます。

まず、MapWrapperクラスを実装します。その後、

class MapWrapper { 
    private: 
    Map *theMap; 
    public: 
    ... 
}; 

と、このようなあなたの動物を構築:private継承が一般化/専門ではないことを

class Dog : public Animal, private MapWrapper { 
}; 

注意、いくつかの種類を実装するだけでトリック強い組成の

もう1つの可能性は、中間クラスをAnimalDogの間に導入することです。 Animalはおそらく純粋な抽象クラスまたはコントラクトなので、実際にはそれを修正するのはおそらく公正ではありません。ただ、AnimalMapを紹介:

class AnimalMap : public Animal { 
    // everything for the map 
}; 
class Dog : public AnimalMap { 
}; 
+0

私に最初の例を教えてもらえますか? MapWrapperに含まれるもの、マップ上で動作するメソッド、またはMapオブジェクトのアクセサーだけですか?私はこの考えを完全に理解していません –

+0

あなたが望むように、それはあなたのニーズに合ったアダプターか、地図にアクセスするための非常に単純なラッパーとして見ることができます。 –

0

変数や関数は、基本型のすべての派生型のために必要な場合は、その変数や関数は、基本型の一部である必要があります。これは継承の前提であり、論理的かつ体系的な方法でコードの重複排除が行われます。

あなたは、Animalオブジェクトが決して実際にマップを使用しないという事実に苦労していると述べました。動物が抽象クラスであることを含む型階層の設計を考えましたか?つまり、Animalは決してインスタンス化されません。これは、与えられた例で概念的に意味をなさない - 動物は動物だけではない。動物のカテゴリには、犬や猫のような他の多くの具体的な概念が含まれます。

私はこの実装があなたの例に合っていて、あなたの哲学的な難点を解決することをお勧めします。

0

マップオブジェクトは、すべてのサブクラスの動物クラスプロパティを継承しているため、動物クラスのみで定義されます。

それが利点である、あなたは動物のクラスのオブジェクトを作成することができ、そしてそれは、オブジェクトのメモリサイズに来るとき、あなたがそこに、動物のクラス

で任意の純粋仮想メソッドを持っていなかったまではマップにアクセスすることができますベースクラスまたは派生クラスのいずれであろうと、マップを保持している場所との違いはありません。派生オブジェクトのサイズは同じだけです

class animal 
{ 
     public: 
       int animal_id; 
       int animal_age; 
}; 
class dog :public animal 
{ 
     public: 
       int dog_type_id; 
}; 
int main() 
{ 
     dog d1; 
     animal a1; 
     cout<<"sizeof d1:"<<sizeof(d1)<<endl; 
     cout<<"sizeof a1:"<<sizeof(a1)<<endl; 
     return 0; 
} 
関連する問題