2015-12-30 36 views
1

我想實現一些具有多態性的類的層次結構,但我無法使其工作。 我有兩個問題:具有額外私有屬性的派生類

  1. 派生類中有多餘的私有變量
  2. 派生類的方法採取作爲參數的派生類的對象,並返回派生類的對象。

我可以使這個代碼工作,但以一種非多態的方式。這是簡化版本:

class Base 
{ 
protected: 
    int mInt; 
public: 
    Base(int iValue) : mInt(iValue) {} 
    virtual Base operator+(const Base otherBase) 
    { 
     Base result(otherBase.mInt + mInt); 
     return result; 
    } 

}; 

class Derived : public Base 
{ 
private: 
    double mDouble; 
public: 
    Derived(int iValue, double dValue) : Base(iValue) 
    { 
     mDouble = dValue; 
    } 
    Derived operator+(const Derived otherDerived) 
    { 
     Derived result(otherDerived.mInt + mInt, 
         otherDerived.mDouble + mDouble); 
     return result; 
    } 

}; 

int main() 
{ 

    Derived DobjectA(2,6.3); 
    Derived DobjectB(5,3.1); 
    Base* pBaseA = &DobjectA; 
    Base* pBaseB = &DobjectB; 
    // This does not work 
    Derived DobjectC = (*pBaseA)+(*pBaseB); 

} 

我如何設計類,使這項工作?

+1

也許這可能有助於http://stackoverflow.com/questions/274626/what-is-object-slicing –

+0

你期望什麼如果'pBaseB'實際上指向一個'Base'對象(或者任何其他派生類型 - 除了派生的 - 就此而言),會發生嗎? – Amit

+0

@Amit我認爲最好的解決方案是拋出一個異常,如果pBaseB指出的類型不是派生的。 – Msegade

回答

2

這裏的關鍵是隱藏在幕後的實際對象的類型,使得它能夠以一種有意義的操作上不知道實際的類型。

我們需要一些方法來確定我們實際上有什麼樣的「東西」:

enum ThingType { TypeA, TypeB } ; 

我們需要一個類,它是一個接口:

class ThingInterface 
{ 
public: 
    /* Type of the object */ 
    virtual ThingType Type() = 0; 
    /* Make a copy of ourselves */ 
    virtual ThingInterface* Clone() = 0; 
    /* Add rhs to this */ 
    virtual void Add(ThingInterface *rhs) = 0; 
    virtual ~ThingInterface(); 
}; 

然後,我們需要一個類支持我們的實際操作:

class Thing 
{ 
public: 
    /* Create empty object */ 
    Thing(ThingType type) { ... } 
    /* Create copy of existing object */ 
    Thing(ThingInterface* rhs) 
    { 
     pImpl = rhs->Clone(); 
    } 

    Thing operator+(const Thing& rhs) 
    { 
     Thing result(pImpl); 
     result.pImpl->Add(rhs.pImpl); 
     return result; 
    } 
private: 
    ThingInterface *pImpl; 
}; 

現在我們可以實現一些類來做不同的類型o ˚F件事:

class ThingTypeA: public ThingInterface 
{ 
public: 
    ThingTypeA() { ... }; 
    ThingType Type() { return TypeA; } 
    void Clone(ThingInterface *rhs) { ... } 
    void Add(ThingInterface *rhs) { ... } 
}; 


class ThingTypeB: public ThingInterface 
{ 
public: 
    ThingTypeA() { ... }; 
    ThingType Type() { return TypeB; } 
    void Clone(ThingInterface *rhs) { ... } 
    void Add(ThingInterface *rhs) { ... } 
}; 

顯然,對於一個矩陣實現,你就需要有一些通用的「讓我含量細胞的X,Y」,即在兩個ThingTypeAThingTypeB實現 - 也許還更多的東西巧妙當涉及到搞清楚什麼類型的結果矩陣應爲TypeA + TypeB

+0

好的解決方案..但是正如你自己指出的那樣,TypeA + TypeB'的含義是一個問題。這個不成立。試圖通過'+'/'Add'收集不兼容的類型是一個設計錯誤。 – 4386427

+0

不,這不是一個設計錯誤 - 這是一個有領域知識的人(換句話說,知道如何最好地計算出稀疏矩陣)的問題。 'Add'函數將不得不將rhs轉換爲與自身兼容的函數,或者使用虛函數將數據轉換爲行,列或單元格的相關格式,具體取決於獲取數據的複雜程度數據與時間的開銷是最好的。 –

+0

嗯......好吧..我必須承認,很久以前,我帶着我的主人,其中包括電氣工程稀疏矩陣的研究,所以事情可能從那時起就發生了變化。不過,我確信OP在錯誤的軌道上。 – 4386427

-1

爲了使問題的老本行,你可以使用動態轉換:

Derived DobjectC = *(dynamic_cast<Derived*>(pBaseA)) + *(dynamic_cast<Derived*>(pBaseB)); 
+0

好的,那是有效的。但是這並不能解決多態性的問題。我不能在派生類可以的任何地方使用基類指針。 – Msegade

+0

'dynamic_cast'的結果並不保證是一個有效的指針 - 它可能是nullptr,在這裏你不需要關心這些東西就可以愉快地解引用它。 – Puppy

+0

@Puppy是的,當然你是對的。但我並沒有試圖回答關於dynamic_cast語義的問題,因爲這完全是另一個問題。在這個問題的背景下,解決方案按預期進行編譯和運行。 –

相關問題