2011-12-21 74 views
1

我在嘗試從指向其基類的指針創建類的副本時遇到了一些麻煩。如何從基類指針複製繼承類而不拼接?

#include <iostream> 
#include <vector> 

class Base { 
    public: 
    Base() { } 
    virtual void test() { std::cout << "I am just the base class\n"; } 
}; 

class First : public Base { 
    public: 
    First() { } 
    void test() { std::cout << "This is the First class\n"; } 
}; 

class Second : public Base { 
    public: 
    Second() { } 
    void test() { std::cout << "This is the Second class\n"; } 
}; 

int main() { 
    First *f = new First(); 
    Second *s = new Second(); 

    // First, I keep a vector of pointers to their base class 
    std::vector<Base *> ptrs; 
    ptrs.push_back(f); 
    ptrs.push_back(s); 
    ptrs[0]->test(); // Properly calls the implemented virtual class by inheritor 
    ptrs[1]->test(); // Properly calls the implemented virtual class by inheritor 

    // Now, I want to *copy* the class without it being spliced to just the base class 
    // from the ptrs vector (not from 'f') 
    First *f2 = new First(*ptrs[0]); 
} 

我最終得到的錯誤是::

test.cpp: In function ‘int main()’: 
test.cpp:35: error: no matching function for call to ‘First::First(Base&)’ 
test.cpp:12: note: candidates are: First::First() 
test.cpp:10: note:     First::First(const First&) 

有沒有什麼辦法來施放此指針複製完整的反對,而不僅僅是基類最好是通過這個例子說明?或者我需要存儲一個指向繼承者的指針來完成這個工作?

回答

3

你可以這樣做:

First *f2 = 0; 
if (typeid(*ptrs[0]) == typeid(First)) 
    f2 = new First(*dynamic_cast<First*>(ptrs[0])); 

這應該工作。

但更好的方法是在基類clone()虛函數,並實現它的派生類:

class Base 
{ 
    public: 
    virtual ~Base() { } //virtual destructed added by me! 
    virtual Base *clone() = 0; 
}; 

class First : public Base 
{ 
    public: 
    virtual First *clone() { /* implement it */ } //Covariant return type 
}; 

而且

First *f2 = 0; 
if (typeid(*ptrs[0]) == typeid(First)) 
    f2 = ptrs[0]->clone(); //no need to use new 

要注意兩點:

  • 我已經添加了虛擬析構函數到基類。看到this topic知道你爲什麼可能需要它。
  • 我在派生類中使用了clone()的不同返回類型。它被稱爲covariant return type
1
First *fx=(First*)ptrs[0]; 
First *f2 = new First(*fx);