2012-03-03 5 views
0

私は、以下の例のような状況でクラスを設計するためのアドバイスをしたいと思います。 BおよびCオブジェクトには、数値コンポーネントがある場合とない場合があります。問題は、NumberComponentコンストラクタを選択的に呼び出す方法がないことです。これを設計するより良い方法はありますか?より良いデザインがありますがクラス設計の苦境

class NumberComponent 
{ 
public: 
//Objects which don't have a number component just store a null pointer. 
//Any time we do anything here, we have to make sure p_int isn't null. 
NumberComponent() : p_int(0) { } 
NumberComponent(int x) { p_int = new int(x); } 
~NumberComponent() { delete p_int; } 

void DoSomething() { if(p_int) ++(*p_int); } 

//In real situation, this will be another complex class object. 
//Using an int* here to keep this class simple for example. 
int* p_int; 
}; 

//B objects may or may not have a number component. 
class B : public NumberComponent 
{ 
public: 
//If hasNumberComponent is false, we'd like to call the default constructor. 
//If hasNumberComponent is true, we'd like to call NumberComponent(int) constructor. 
B(int x, bool hasNumberComponent) {} 

int value; 
}; 

//C objects may or may not have a number component. 
class C : public NumberComponent 
{ 
public: 
//If hasNumberComponent is false, we'd like to call the default constructor. 
//If hasNumberComponent is true, we'd like to call NumberComponent(int) constructor. 
C(int x, bool hasNumberComponent) {} 

int value; 
}; 

int main() 
{ 
//myList contains NumberComponent* to B and C objects 
std::list<NumberComponent*> myList; 

myList.push_back(new B(5, true)); 
myList.push_back(new C(3, true)); 

for(std::list<NumberComponent*>::iterator i = myList.begin(); i != myList.end(); ++i) 
    (*i)->DoSomething(); 

//These objects don't have a Number component. 
B b(2, false); 
C c(1, false); 

return 0; 
} 
+1

'B'と 'C'がNumberComponent' 'から派生した場合は、その後、彼らは**' NumberComponent'sです。だから、彼らは「数的要素を持っているかもしれないし、持たないかもしれない」と言っても意味がありません。 –

+1

ちなみに:あなたがする必要がない限り、動的に割り当てられたオブジェクトを(つまり 'new'を介して)使用しないでください。私は、あなたのサンプルコードで 'new'を使用する理由を見ることができません! –

+0

私はこれについてどう考えているのか少し混乱していると思います。私はいくつかのBとCオブジェクトがp_intを持っていて、DoSomething()のようなことをすることができるようにしたいと思います。他のBとCのオブジェクトは、p_intを必要とせず、DoSomething()のようなことをすることができないという点を除いて同じです。 – user987280

答えて

0

、あなたはこのようなあなたの当面の問題を解決することができます:悪いデザインの多くがここにあります

class NumberComponent 
{ 
public: 
NumberComponent(int x,bool hasNumberComponent) 
    : p_int(hasNumberComponent ? new int(x) : 0) { } 
~NumberComponent() { delete p_int; } 

void DoSomething() { if(p_int) ++(*p_int); } 

//In real situation, this will be another complex class object. 
//Using an int* here to keep this class simple for example. 
int* p_int; 
}; 

//B objects may or may not have a number component. 
class B : public NumberComponent 
{ 
public: 
B(int x, bool hasNumberComponent) : NumberComponent(x,hasNumberComponent) {} 

int value; 
}; 

//C objects may or may not have a number component. 
class C : public NumberComponent 
{ 
public: 
C(int x, bool hasNumberComponent) : NumberComponent(x,hasNumberComponent) {} 

int value; 
}; 
0

。あなたはそれがために発明されたもののために継承を使用するために考えた:

class B 
{ 
    public: 
     B(int x): 
     m_val(x) 
     { 
     } 

     virtual void doSomething() 
     { 
      //something 
     } 

    private: //might be protected as well 
     m_val; 
}; 

class BWithNumberComponent : public B 
{ 
    public: 
    BWithNumberComponent(int x): 
     B(x), 
     m_numberComponent(x) 
    { 
    } 

    virtual void doSomething() 
    { 
     //something else 
    } 

    private: 
    NumberComponent m_numberComponent; 
}; 
+0

これは、私がNumberComponentを使用するオブジェクトのstd :: listを持つことができないことを除いて、デザインを賢明にするためのより良い方法のようです。私はそれらのDoSomething()を呼び出すことができるようにNumberComponent機能を持つBとCの両方のオブジェクトのリストを持つことができるようにしたい。私はこれを行う唯一の方法は、BとCの両方が同じ親クラスから継承されるようにすることだと思います。 – user987280

+0

@ user987280同じ親クラスですが、必ずしもオブジェクトの特別な機能のように見える 'NumberComponent'とは限りません。あなたはそれがプロパティに提供された余分なインタフェースを分解することによって構造体を平坦化しました(何も起こらない場合はfalseです)。また、あなたのオブジェクトの責任を混乱させないでください。 'B'と' C'の共通メソッドが必要な場合は、抽象仮想メソッド 'doSomething()'を使って純粋な抽象クラス 'DoSomethingInterface'を定義し、継承して' B'と 'C'に実​​装します。 – doc