how to copy an inherited class from its base class pointer without splicing?
我在尝试创建一个从指针到它的基类的类副本时遇到了一些困难。最好通过这个例子来说明:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | #include <iostream> #include <vector> class Base { public: Base() { } virtual void test() { std::cout <<"I am just the base class "; } }; class First : public Base { public: First() { } void test() { std::cout <<"This is the First class "; } }; class Second : public Base { public: Second() { } void test() { std::cout <<"This is the Second class "; } }; 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]); } |
我最后得到的错误是:
1 2 3 4 | 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&) |
是否有任何方法可以强制转换此指针来复制完整的对象,而不仅仅是基类?或者需要存储一个指向继承者的指针才能使其工作?
您可以这样做:
1 2 3 | First *f2 = 0; if ( typeid(*ptrs[0]) == typeid(First)) f2 = new First(*dynamic_cast<First*>(ptrs[0])); |
那应该管用。
但更好的方法是在基类中使用
1 2 3 4 5 6 7 8 9 10 11 12 | 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 }; |
和
1 2 3 | First *f2 = 0; if ( typeid(*ptrs[0]) == typeid(First)) f2 = ptrs[0]->clone(); //no need to use new |
需要注意的两点:
- 我已经向基类添加了虚拟析构函数。查看此主题以了解您可能需要它的原因。
- 我在派生类中对
clone() 使用了不同的返回类型。它被称为协变返回类型。
1 2 | First *fx=(First*)ptrs[0]; First *f2 = new First(*fx); |