9

我想创建一个名为“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]

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

4

6 回答 6

9

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

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

Node::~Node()
{
  // Compulsory virtual destructor definition,
  // even if it's empty
}
于 2012-12-21T11:42:25.580 回答
7

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

§ 12.1 构造函数

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

下面的代码不会编译:

virtual Node::Node() = 0;

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

是的,使析构函数成为纯虚函数,还提供析构函数定义

class Node 
{
public:
    virtual ~Node()=0
    {
    }
};
于 2012-12-21T11:48:45.537 回答
4

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

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

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

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

编辑确保你记录你为什么使用纯虚拟析构函数。代码本身在这方面是神秘的,并没有让不知道这个“技巧”的人清楚。

编辑 2您的构造函数应该是protected,而不是private。如果您的构造函数是private.

于 2012-12-21T11:40:49.477 回答
0

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

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

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

于 2012-12-21T11:40:37.280 回答
0

简单地:

class Node 
{
protected:
    Node()
    {
    }
public:
    virtual ~Node()
    {
    }
}
于 2012-12-21T11:40:50.287 回答
0

你想做的是

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;**

于 2012-12-21T12:25:49.563 回答