2014-12-05 69 views
2

我遇到了複製構造函數的問題......我假設有一個基本的答案,我錯過了一些顯而易見的東西 - 也許我正在做一些完全錯誤的事情 - 但我一直無法弄清楚。父類/子類的C++複製構造函數問題

基本上,我有一個父類和子類。父類包含一個指向(不同)基類對象的指針向量。子類想要存儲指向從該基礎對象派生的對象的指針。

下面是一個僞代碼示例,如果這能幫助:

// Base classes 
class ItemRev { 
    ... 
} 

class Item { 

protected: 

vector<ItemRev *> m_revPtrVec; 

} 


Item::Item(const Item &inputItemObj) 
{ 
    // Copy contents of the input object's item rev pointer vector 
    vector<ItemRev *>::const_iterator vecIter = (inputItemObj.m_revPtrVec).begin(); 
    while (vecIter != (inputItemObj.m_revPtrVec).end()) { 
    (this->m_revPtrVec).push_back(new ItemRev(**vecIter)); 
    } 
} 

========= 

// Derived classes 
class JDI_ItemRev : public ItemRev { 
    ... 
} 

class JDI_Item : public Item { 

... 

} 

JDI_Item::JDI_Item(const JDI_Item &itemObj) 
{ 
    // Copy contents of the input object's item rev pointer vector 
    vector<ItemRev *>::const_iterator vecIter = (inputItemObj.m_revObjPtVec).begin(); 

    // The below does not work! 
    while (vecIter != (inputItemObj.m_revObjPtVec).end()) { 
    m_revObjPtVec.push_back(new JDI_ItemRev(**vecIter)); 
    } 
} 

的問題上面是在JDI_Item拷貝構造函數的調用push_back()

鑑於此設置,子類的複製構造函數應該是什麼樣子?我甚至需要一個子類複製構造函數嗎?我以爲我做了,因爲複製構造函數創建新對象,並且父複製構造函數將創建新的對象,這些對象不是我想要的派生類中的類型(即,父對象存儲指向ItemRev對象的指針,而子對象應該存儲指向派生的JDI_ItemRev對象的指針)。

+0

您將需要一個拷貝從基構造,與簽名'JDI_Item :: JDI_Item(常量ItemRev&)'東西。這個構造函數不是默認爲你生成的,因爲它很少有意義。 – cdhowie 2014-12-05 23:31:31

+0

首先,'JDI_Item'-ctor是越野車。如果發生任何異常,它會泄漏。爲什麼你總是有'std :: vector'指針指向'JDI_ItemRev'?爲什麼他們不直接在向量中,或者至少由智能指針管理? (在第一種情況下,隱式定義應該起作用。)對「Item」也可以這麼說。 – Deduplicator 2014-12-05 23:31:57

回答

1

正如在評論中提到的那樣,可能有更簡潔的方式來表達這個問題(即你的類結構需要一些工作)。

但是,如果您想這樣做,最簡單的方法是在基類ItemRev中使用虛擬clone()方法,並在派生類中定義它的覆蓋。

例如爲:

class ItemRev { 

    virtual ItemRev* clone() const = 0; 
}; 

class JDI_ItemRev : public ItemRev { 

    ItemRev* clone() const override 
    { 
    // do your actual cloning here, using the copy constructor 
    return new ItemRev(*this); 
    } 
}; 

現在,每當你從ItemRev派生的任何類叫clone(),你將返回ItemRev*但它會指向一個完全構造派生類。您當然可以通過static_cast<>dynamic_cast<>來獲得派生類的接口。

... ...但是

推導往往似乎是一個輕鬆取勝,但結果往往並非如此。只有派生類確實是基類的類型時才應該使用繼承。通常人們在派生類很像基類時選擇繼承,或者基類共享很多特性。這不是使用繼承的時候。現在是使用封裝的時候了。

一般來說,繼承是邪惡的。

另一方面,你可能會發現這個鏈接有趣。

Presentation on inheritance as an implementation detail