在 C++ 中创建派生抽象类的实例
Posted
技术标签:
【中文标题】在 C++ 中创建派生抽象类的实例【英文标题】:Create instance of derived abstract class in c++ 【发布时间】:2015-07-10 14:22:03 【问题描述】:我遇到了这个问题,不知道怎么解决。
假设我有这些基类:
class ValueBase
private:
int base_value;
public:
int GetValue();
void SetValue(int val);
virtual ValueBase* Meet(ValueBase* const a, ValueBase* const b) = 0;
class NodeBase
private:
ValueBase* base_nodeValue;
public:
bool AddValue(int val);
和派生类:
class Value : public ValueBase
public:
Value* Meet(ValueBase* a, ValueBase* b) override;
有没有办法在类NodeBase
中的方法AddValue
中创建类Value
的实例?我知道我可能应该将AddValue
设为纯虚拟并在NodeBase
的派生类中实现它,但是如果没有这个选项,是否有可能做到这一点?我可以使用例如模板方法或者可能是 Value
中将构造该对象的方法的回调?还是这样做太邪恶了?
编辑:
我无权访问 NodeBase
类中的派生类 Value
【问题讨论】:
bool AddValue(int val) base_nodeValue = new Value;
繁荣,完成。
对,我错过了一次,请查看编辑。
你不能转发声明Value
,或者包含正确的标题以便在NodeBase
中使用它吗?
@JonathanPotter 将此作为答案,以便可以接受
问题的标题是错误的和误导性的,它暗示你想创建一个抽象类的实例,这当然是不可能的。您想创建一个派生类的实例的事实 from 一个抽象类是无关紧要的,你可以说“创建派生类的实例”,因为这就是你想要做的,它不会基础是否抽象的区别。
【参考方案1】:
添加创建成员函数:
class ValueBase
public:
virtual ValueBase * create() = 0;
// ...
;
那么在NodeBase
你可以使用base_nodeValue->create()
。
派生类实现它:
class Value : public ValueBase
Value * create() override return new Value;
;
这种模式更常见的形式是 clone 函数,但它不会生成相同类型的默认构造对象,而是 copy:
Derived * clone() override return new Derived(*this);
【讨论】:
这并不能解决任何问题。使用这种方法,您需要正确派生类型的对象才能创建正确派生类型的对象。 OP 显然想要创建一个但还没有一个。 @KerrekSB,当我阅读问题时,它可能是 NULL 或其他什么 @JSF,我认为这根本不是“明显”的情况。 OP 说“可能是对Value
中方法的回调”,这强烈表明拥有一个可以调用该方法的对象是一个有效的考虑因素。【参考方案2】:
我看不到不改变类定义的方法。但是,有许多方法涉及更改类定义,具体取决于“允许”使用的内容。
A.将 AddValue()
模板化为它应该创建的对象类型:
class NodeBase
private:
ValueBase* base_nodeValue;
public:
template<class ValueType>
bool AddValue(int val) base_nodeValue = new ValueType;
...
// other code that has access to Value
node.AddValue<Value>(10);
B.创建创建Value
的函数(如果需要,将任何参数转发给构造函数) and pass it as an argument to
AddValue`:
// might need to adapt syntax
class NodeBase
private:
ValueBase* base_nodeValue;
public:
bool AddValue(int val, ValueBase* (*creator)()) base_nodeValue = (*creator)();
...
// other code that has access to Value
ValueBase* valueCreator() return new Value;
...
node.AddValue(10, valueCreator);
(也可以在这里使用仿函数或 lambda)
C.您可以在ValueBase
中创建一个返回Value*
的函数。
class ValueBase
public:
static ValueBase* createValue();
;
class NodeBase
private:
ValueBase* base_nodeValue;
public:
bool AddValue(int val) base_nodeValue = ValueBase::createValue();
;
// in a separate cpp
ValueBase* ValueBase::createValue() return new Value;
这实际上类似于工厂方法:您可以让createValue()
接受一个参数并根据它创建不同的ValueBase
s。让ValueBase
存储一些指向创建函数的指针,您可以让它根本不知道Value
,只需在其他地方初始化该指针,就像您可以在基类的工厂表中注册一个子类一样。
【讨论】:
谢谢你,对我来说真的很棒的答案 :) 我最终使用了模板方法,并且使用了一些static_assert
效果很好以上是关于在 C++ 中创建派生抽象类的实例的主要内容,如果未能解决你的问题,请参考以下文章