我想编写一个适用于某个层次结构中任何派生类的函数,而不修改抽象类输入参数:
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?
答案 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); }
};