如何从基类指针复制一个继承的类而不进行拼接?

时间:2011-12-21 07:17:33

标签: c++ class inheritance

我在尝试从指向其基类的指针创建类的副本时遇到了一些麻烦。最好通过这个例子来说明:

#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&)

有没有办法将此指针转换为复制完整的对象,而不仅仅是基类?或者我是否需要存储指向继承者的指针才能使其工作?

2 个答案:

答案 0 :(得分: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

需要注意两点:

  • 我已将虚拟析构函数添加到Base类。请参阅this topic以了解您可能需要它的原因。
  • 我在派生类中使用了clone()的不同返回类型。它被称为covariant return type

答案 1 :(得分:1)

First *fx=(First*)ptrs[0];
First *f2 = new First(*fx);