2013-03-28 74 views
4

我想写的是在一定的层次结构的任何派生类工作的功能,而无需修改抽象类的输入参数:如何从纯抽象基类引用创建对象副本?

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的工作,但我可以” t创建具体类的副本,因为我不知道实际类型,除非使用dynamic_cast。

是否有另一种方法来解决这个问题或应该只使用dynamic_cast?

+0

为什么F()需要做一个副本? – andre

+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; 
}; 
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); } 
}; 
+0

我需要进行复制,因为我无法直接修改输入常量引用。我无法调用该参数的add(),我不能'更改函数签名。 –

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*' 
                 ^^^^^^^^ 

根据您的回应的另一种选择是让m_imutable,使成员方法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 
} 
+0

我不想修改输入参数。 –

+0

@RobertKubrick'add'突变了这个类,所以你不能把它作为'const'传递并调用'add'。如果你想调用另一个'const'函数,而不是'add',那么这将起作用。 –

+0

@RobertKubrick,除非你想声明'm_i'为'mutable' –