2012-03-03 67 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。所以說他們「可能有或沒有數字組件」是毫無意義的。 – 2012-03-03 22:10:05

+1

順便說一句:不要使用動態分配的對象(即通過'new'),除非必須。我看不出有什麼理由在你的示例代碼中使用'new'! – 2012-03-03 22:10:50

+0

我覺得我對於如何思考這個有點困惑。我想讓一些B和C對象有一個p_int並能夠做DoSomething()之類的事情。其他B和C對象將是相同的,除了它們不需要p_int並且不應該能夠執行諸如DoSomething()之類的操作。 – user987280 2012-03-03 22:17:59

回答

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 ::列表。我希望能夠擁有包含NumberComponent功能的B和C對象的列表,以便我可以對它們調用DoSomething()。我認爲唯一的方法是讓B和C都從同一個父類繼承。 – user987280 2012-03-04 00:30:26

+0

@ user987280相同的父類,但不一定是'NumberComponent',這似乎是您的對象的某種額外功能。你通過降低提供給屬性的額外接口來平坦化你的結構(如果它沒有發生任何錯誤)。也不要混淆你的對象的責任。如果你需要一些'B'和'C'的通用方法,那麼用抽象虛擬方法'doSomething()'定義純粹的抽象類'DoSomethingInterface',繼承它並在'B'和'C'中實現。 – doc 2012-03-04 02:08:55