2013-05-01 42 views
3

我試圖子對象傳遞給方法任何子對象,但不知道輸入對象的時間提前,除此之外,它會從父繼承。 我可以將類型設置爲父類,並且編譯器很高興,但是當此過程發生時,我會丟失子數據。C++通過與父類型的方法

class Parent{ 
public: 
Parent(int val); 
}; 

class Child{ 
public: 
Child(double childval, int parentval) 
}; 

Child::Child(double childval, int parentval) : Parent(parentval) 

Child childObj = new Child(cval, pval); 

int someOtherMethod(Parent pobj); 
someOtherMethod(childObj); // Looses child data but parent data persists. How to keep child data too? 

是好的,但是如果我通過childObj到someOtherMethod子數據丟失,只有父數據保持不變。

我已經看過成虛函數,動態綁定,「set」,但已成爲完全搞不清我應該採取的方向。

可有人請讓我回到正軌?

謝謝。

+0

發佈您的實際代碼,最好編譯 – yngccc 2013-05-01 00:35:35

+0

「傳遞一個子對象的方法,但不知道輸入對象提前」 <是不是意味着類型是孩子???? – marcadian 2013-05-01 00:35:58

+0

@marcadian對象類型可以是大約4種繼承類型中的任何一種,Child1,Child2等 – 2013-05-01 00:37:54

回答

1

項目的類在刀刃上,用多態,定義良好的接口,以獲得從子類的數據。

但是,如果你需要用C++做垂頭喪氣,你可以做到這一點與dynamic_cast<T>

int someOtherMethod(Parent *pobj); 
{ 
    Child1 *c1; 
    Child2 *c2; 
    Child3 *c3; 
    Child4 *c4; 



    if((c1= dynamic_cast<Child1*>(pobj)) != 0) 
    { 
     /* Do stuff here, pobj is instance of Child1 */ 
    } 
    else if((c2 = dynamic_cast<Child2*>(pobj)) != 0)) 
    { 
     /* Do stuff here, pobj is instance of Child2 */ 
    } 

    // ... 
} 

通過你的參數爲指針的方法,你將需要至少有一個虛函數在你的班級爲了這個工作。

2

由於維迪奇硼酸指出的那樣,你有一個選擇是使用動態演員。但是,對於一些編譯器(如MSVC),使用動態強制轉換可能會造成代價高昂,因此在評估指針時會運行字符串比較。

你有另一種選擇是使用靜態鑄造。靜態轉換在編譯時進行評估,因此幾乎沒有使用它們的成本。但是,您仍然必須有一種方法來確定您的類的類型,以便知道要將其轉換爲什麼類型。在你的基類中,你可以有一個名爲getType()的純虛函數,它返回一個枚舉值或一個無符號整數,表示該類的id。然後,您可以在「someOtherMethod」內部檢查傳入的類的id類型,然後對該類類型執行類型轉換。

E.g.

在一些文件中定義與類型

enum ClassTypes 
{ 
    ClassType1, 
    ClassType2, 
    ... 
}; 

作爲一個方面說明枚舉:如果不改變什麼pObj點,你會想使指針 常量。它可以讓讀者知道你不打算任何人改變它,它也是一種防禦編程的形式,對付你最大的敵人(你自己),確保你不會意外地改變它,然後嘗試在它上面進行演員表。

int someOtherMethod(Parent * const pObj) 
{ 
    if(pObj == NULL) 
     return 0; 

    switch(pObj->getType()) 
    { 
     case ClassType1: 
     { 
      Class1 * const pClass = static_cast<Class1*>(pObj); 
      //Do stuff to class type 1 
      break; 
     } 
     case ClassType2: 
     { 
      Class2 * const pClass = static_cast<Class2*>(pObj); 
      break; 
     } 
    }; 

    return 1; 
} 

正如你可以看到,雖然這可能會迅速增長,它不會處理重複的代碼一切都好。此外,Static Cast可能很危險,因爲在運行時沒有檢查,看看你正在投射的東西是否有可能導致崩潰。

你必須要考慮的類本身的設計。也許你想在這個函數中執行的代碼可以在類中執行。因此,不必知道類型,你可以簡單地說:

pObj-> someOtherMethod(),其中someOtherMethod是您的孩子必須定義的純虛函數。您可能會在多個方法定義中重複運行代碼,在這種情況下,某些設計模式(如NVI模式)可能會派上用場。

2

如果孩子素顯示或孩子採取行動,不會在父抽象所屬的信息,那麼你可以判斷孩子是通過動態鑄造或檢查類型誰。然而,正如Edward Corlew所說,這有一些缺點。

或者,你可以問孩子這是一個雙重派遣誰。這可以通過將對象傳遞給孩子來完成,然後孩子選擇它的類型。然後訪客可以收集所需的任何信息。

class Child1; 
class Child2; 

class Visitor 
{ 
public: 
    void DoStuff(Child1 & child1); 
    void DoStuff(Child2 & child2); 
}; 

class Parent 
{ 
public: 
    void DoStuff(Visitor & visitor); 
}; 

class Child1 : public Parent 
{ 
public: 
    void DoStuff(Visitor & visitor) 
    { 
    visitor.DoStuff(*this); 
    } 
}; 

class Child2 : public Parent 
{ 
public: 
    void DoStuff(Visitor & visitor) 
    { 
    visitor.DoStuff(*this); 
    } 
}; 

潛在地,訪問者本身可能來自並允許不同的操作。這消除了在整個程序中傳播類型檢查的需求。但是,訪問者類本身與派生的子項相關聯,並且在添加具體子項時需要更新。