【问题标题】:Inheritance from empty base class in C++从 C++ 中的空基类继承
【发布时间】:2012-12-08 23:50:23
【问题描述】:

我想创建一个名为“Node”的空基类,然后从它派生其他类,例如“DecisionNode”和“Leaf”。这样做是有意义的,因此我可以利用多态性将这些不同类型的节点传递给方法,而无需在编译时知道将传递给方法的内容,但是每个派生类不共享任何状态或方法。

我认为实现这一点的最佳方法是使构造函数成为纯虚拟,而不在基类中创建额外的纯虚拟方法,这会增加混乱。因此,在该类的头文件“Node.h”中,我写道:

class Node {
 private:
  virtual Node();
};

我在“Node.cpp”中写道:

#include "Node.h"
virtual Node::Node() = 0;

此实现防止 Node 被另一个类实例化,因为唯一的构造函数是私有的,并且使用纯虚拟说明符来指示该类是抽象的。但是,这会导致编译器错误:

Node.h:6:21: error: return type specification for constructor invalid
Node.h:6:21: error: constructors cannot be declared virtual [-fpermissive]

我的问题是:有没有一种巧妙的方法来制作一个空的抽象基类?

【问题讨论】:

  • 使用虚拟析构函数,无论如何你都应该这样做。
  • 如果没有节点共享方法,你实际上打算如何使用节点
  • stackoverflow.com/questions/9588788/… 在问题中有一个 ABC 实现。
  • @WaleedKhan:在方法签名中,所以我可以传入任何从 Node 派生的类。
  • @Froskoy,如果他们不共享代码并且没有任何虚拟方法,那么传递 Node* 并不比传递 void* 好 - 在这两种情况下,您都必须转换为来回特定的类。

标签: c++ inheritance constructor polymorphism abstract-class


【解决方案1】:

你不能将构造函数设为虚拟。如果不需要其他纯虚函数,您可以将析构函数设为纯虚函数:

class Node
{
public:
    virtual ~Node() = 0;
};

Node::~Node()
{
  // Compulsory virtual destructor definition,
  // even if it's empty
}

【讨论】:

  • 但他似乎也想阻止“平民”创建Node的实例
  • 使用这种方法,您不能创建类节点的实例,只能保存对派生类型节点的引用。
【解决方案2】:

C++ 不支持虚拟构造函数。

§ 12.1 构造函数

12.1.4 构造函数不应是虚拟的 (10.3) 或静态的 (9.4)。

以下代码无法编译:

virtual Node::Node() = 0;

我的问题是:有没有一种巧妙的方法来制作一个空的抽象基础 上课?

可以,让析构函数成为纯虚函数,同时提供析构函数定义

class Node 
{
public:
    virtual ~Node()=0
    {
    }
};

【讨论】:

  • 这行不通,至少在 g++ 上不行。您必须在类定义之外提供构造函数的定义。
【解决方案3】:

创建一个虚拟析构函数并提供一个“空”实现。

class Node {
    virtual ~Node() = 0;
}

Node::~Node() {}  // You will get linker error if you do not have this

正如其他人所评论的那样,另一种选择是使构造函数受到保护。另请参阅此问题以了解两者之间的一些差异。 protected constructor versus pure virtual destructor

编辑 确保记录下使用纯虚拟析构函数的原因。代码本身在这方面是神秘的,对于不知道这个“技巧”的人来说并不清晰。

编辑 2 你的构造函数应该是protected,而不是private。如果您的构造函数是private,您将无法继承。

【讨论】:

  • 谢谢!我不明白为什么没有实现会出现链接器错误?
  • 那是因为派生类析构函数需要调用基类析构函数。当你自己声明基类析构函数时,编译器不会为你生成一个。
  • 顺便说一下,通过我提供的链接中接受的答案来比较两种方法。 (同样,如果他们对您有帮助,请对答案和问题投赞成票。;))
【解决方案4】:

在 C++ 中,构造函数不能是 virtual。为了防止任何人实例化你的基类,给它一个受保护的构造函数,像这样:

class Node {
protected:
  Node() {}
};

它不会是抽象的,但只有派生类才能创建它的实例。

【讨论】:

    【解决方案5】:

    简单地说:

    class Node 
    {
    protected:
        Node()
        {
        }
    public:
        virtual ~Node()
        {
        }
    }
    

    【讨论】:

      【解决方案6】:

      你想要做的是

      class Node {
       private:
        virtual Node();
      };
      and in "Node.cpp" I wrote:
      
      #include "Node.h"
      // This is the error as your class name and function name i.e. same so compiler assumes 
      // that this as a constructor and as per the c++ standard a constructor can not have 
      // return type as well as can not be virtual
      virtual Node::Node() = 0;
      

      所以你创建一个虚拟析构函数为 ** virtual ~Node() = 0;**

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多