在 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 toAddValue`:

 // 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() 接受一个参数并根据它创建不同的ValueBases。让ValueBase 存储一些指向创建函数的指针,您可以让它根本不知道Value,只需在其他地方初始化该指针,就像您可以在基类的工厂表中注册一个子类一样。

【讨论】:

谢谢你,对我来说真的很棒的答案 :) 我最终使用了模板方法,并且使用了一些 static_assert 效果很好

以上是关于在 C++ 中创建派生抽象类的实例的主要内容,如果未能解决你的问题,请参考以下文章

指向抽象类的指针

在抽象超类的静态方法中创建子类的实例? [复制]

获取派生类以显示与派生类的父类具有聚合关系的抽象类中的变量的 C++ 错误

C++ 抽象类 (abstract class)

我可以根据抽象基类中定义的某个属性创建派生类的实例吗?

关于C++基类、派生类的引用和指针