如何从纯抽象基类引用创建对象副本?

时间:2013-03-28 14:30:44

标签: c++

我想编写一个适用于某个层次结构中任何派生类的函数,而不修改抽象类输入参数:

class A {
public:
    A(int val): m_i(val) { }
    virtual void add(int i) = 0;

    int m_i;
};

class B: public A {
public:
    B(int val): A(val) { }
    B(): A(0) { }
    virtual void add(int i) { m_i += i; }
};

class C: public A {
public:
    C(int val): A(val) { }
    C(): A(0) { }
    virtual void add(int i) { m_i += i*2; }
};

int f(const A& base_class)
{
    // how to create a concrete copy of class base_class?
    base_class.add(5);
}

这里f()应该适用于B和C,但我不能创建具体类的副本,因为我不知道实际的类型,除非我使用dynamic_cast。

是否有其他方法可以解决此问题,还是应该使用dynamic_cast?

3 个答案:

答案 0 :(得分:2)

通常称为virtual constructor idiom的典型方法是定义另一个用于克隆具体类的虚方法,使其在抽象基础中虚拟化,并根据需要调用它以生成所需类的实例,而不知道它类型:

class A {
public:
    A(int val): m_i(val) { }
    virtual void add(int i) = 0;
    virtual A* clone() const = 0; // Override in derived classes to return new B/C
    int m_i;
};

答案 1 :(得分:1)

问题是您传递了const A&add不是const方法,如果您取消const修饰符,则此方法有效:

int f(A& base_class)
{
    // how to create a concrete copy of class base_class?
   base_class.add(5);

   ///Need a return here
}

我正在使用gcc,错误确实告诉你这是怎么回事:

error: no matching function for call to 'A::add(int&) const'
  base_class.add(a);                                  ^^^^^  

no known conversion for implicit 'this' parameter from 'const A*' to 'A*'
                                                        ^^^^^^^^

根据您的回复,另一个选项是make m_i mutable,并使成员方法const如下:

class A {
  public:
    A(int val): m_i(val) { }
    virtual void add(int i) const = 0;

  protected:
    mutable int m_i;
};

class B: public A {
 public:
    B(int val): A(val) { }
    B(): A(0) { }
    virtual void add(int i) const { m_i += i; }
};

class C: public A {
  public:
    C(int val): A(val) { }
    C(): A(0) { }
    virtual void add(int i) const { m_i += i*2; }
};

int f(const  A& base_class)
{
    base_class.add(5) ;

    //Need a return here
}

答案 2 :(得分:0)

您的问题不清楚为什么您甚至需要复制。

但是,如果这样做,您可以使用clone()方法:

class A {
public:
    virtual A* clone() const = 0;
};

class B: public A {
public:
    virtual B* clone() const { return new(*this); }
};

class C: public A {
public:
    virtual C* clone() const { return new(*this); }
};