2009-06-20 139 views
6

考慮:C++:多態複製構造函數可以工作嗎?

class A 
{ 
public: 
    A(int val) : m_ValA(val) {} 
    A(const A& rhs) {} 
    int m_ValA; 
}; 

class B : public A 
{ 
public: 
    B(int val4A, int val4B) : A(val4A), m_ValB(val4B) {} 
    B(const B& rhs) : A(rhs), m_ValB(rhs.m_ValB) {} 
    int m_ValB; 
}; 

int main() 
{ 
    A* b1 = new B(1, 2); 
    A* b2 = new A(*b1); // ERROR...but what if it could work? 
    return 0; 
} 

將c + +,如果被打破的 「新A(B1)」 是能夠解決創造一個新型B拷貝並返回一個

這會甚至有用嗎?

回答

19

您是否需要此功能,或者這只是一個思想實驗?

如果你需要做到這一點,常見的成語是有一個Clone方法:

class A 
{ 
public: 
    A(int val) : m_ValA(val) {} 
    A(const A& rhs) {} 
    virtual A *Clone() = 0; 
    int m_ValA; 
}; 

class B : public A 
{ 
public: 
    B(int val4A, int val4B) : A(val4A), m_ValB(val4B) {} 
    B(const B& rhs) : A(rhs), m_ValB(rhs.m_ValB) {} 
    A *Clone() { return new B(*this); } 
    int m_ValB; 
}; 

int main() 
{ 
    A* b1 = new B(1, 2); 
    A* b2 = b1->Clone(); 
    return 0; 
} 
+5

+1叫,但我也想補充一個虛擬析構函數的類;) – 2009-06-20 14:00:30

+0

這確實是一個思想實驗。雖然這是實現虛擬拷貝構造函數的標準方式,但我很好奇爲什麼這種語言沒有提供一種標準化的方式來實現這一點。 – 0xC0DEFACE 2009-06-21 12:41:03

+0

協變回報更好:B * B :: Clone() – 2018-01-24 17:11:09

0

是。有很多方法可以實現克隆(比如標準克隆(或多或少的方法),對象工廠的參數化變體,有或沒有可配置依賴注入),而不改變現有程序的含義,或者使得當編譯單元中已知派生類時,無法創建基類的實例。

構造函數和析構函數對於初學者來說是相當複雜的。向他們注入更復雜的東西是不明智的。

1

表達

new A(*b1) 

已經有一個意義,假設你有適當的過載。

如果給出了不同的含義,則必須提供另一種方式來獲得其他含義。這是一種毫無意義的因爲已經有辦法得到你想要的含義:

new B(*b1) 

你猜這是更清晰的閱讀。

+1

但第二個例子假定你知道事實上`b1`實際上是`B`。 – user470379 2011-01-19 20:48:19

0

正如上面指出的那樣,有很多方法可以實現這一點。

要回答你的問題,如果new A(*b1)返回一個新的B實例,那麼這將無法正常工作。

int main() 
{ 
    A* b1 = new B(1, 2); 
    A a(*b1); // What size would 'a' be if it was polymorphicly constructed? 
    return 0; 
} 
2

只是一個小除了答覆eduffy: 而不是

class B : public A { 
    ... 
    A *Clone() { return new B(*this); } 
    ... 

};

,你可以像這樣把它聲明:

class B : public A { 
    ... 
    B *Clone() { return new B(*this); } // note: returning B * 
    ... 

};

它仍然被認爲是虛擬A::Clone();的有效壓倒一切的,是更好的,如果直接通過B *