繁体   English   中英

C ++:如果类没有成员函数,如何创建抽象基类?

[英]C++: How to create an abstract base class if class has no member functions?

我有一个抽象基类,其目的是允许创建指向基类的指针数组。 (对于“很多事情有用...”)

我的抽象基类不包含任何成员函数。 因此,没有纯粹的虚拟方法,因此我想它在技术上不是抽象的。

但是,我不希望能够创建此类的实例。

是否可以创建无成员抽象基类? 如果不是,是否还有其他解决方案可以阻止创建“抽象库”实例? 使构造函数protected就足够了吗?

曾经向我指出,实际上,如果抽象类的目的是允许创建指向该基类的向量或指针数组,则不需要该抽象基类-一个人可能根本就没有基类,并且将继承层次结构顶部的类用作基类。 或者,可以复制并粘贴该顶级类,并在没有实现的情况下交换纯虚拟函数的已实现方法,但是,这在逻辑上似乎与抽象基本指针的思想不一致,并且会导致维护代码更加困难。

提供一个纯虚拟析构函数:

struct Base {
 virtual ~Base() = 0;
};

inline Base::~Base() {}

您需要提供一个实现,可以通过将其设置为inline来直接在标头中。


抽象类是具有某些纯虚函数的类:

[...]如果一个类至少具有一个纯虚函数,则它是抽象的。 [...]

[N4431§10.4/ 2]

由于您想要一个指向抽象类实例的指针数组(派生类),因此我假设您还希望最终能够通过这些指针delete并从而破坏这些实例中的一个或多个:

Base * instance = // ... whatever ...
delete instance;

在这种情况下,要调用(派生类的)正确的析构函数,该析构函数必须是虚拟的。

因此,由于这两种方法都是虚拟的,并且您不希望使用某些纯虚拟成员函数,因此最好使析构函数成为纯虚拟的。

要使虚拟函数纯净,请将pure-specifier附加到其声明中:

struct Foo {
 virtual void bar(void) /* the */ = 0; // pure-specifier
};

现在,关于定义,您想知道为什么我们需要提供一个定义,因为...

[...]仅当使用合格ID语法(5.1)或如同(12.4)一样调用纯虚拟函数时,才需要定义。 [...]

[N4431§10.4/ 2]

这是因为在销毁派生类时,在派生类析构函数被调用之后,基类的析构函数也将被调用:

struct Derived : public Base {
 ~Derived() {
  // contents
  // Base::~Base() will be called
 }
};

在执行析构函数的主体之后,类X的析构函数调用X的直接基类的析构函数,如果X是最派生类的类型(12.6.2),则其析构函数调用X的虚拟基类的析构函数。 调用所有析构函数,就好像它们是用限定名称引用的一样。[...]

[N4431§12.4/ 8]

因此,如果需要Base类,则可以定义纯虚拟析构函数。 但是...

[...]函数声明不能​​同时提供纯说明符和定义[...]

[N4431§10.4/ 2]

...因此必须在类定义之外进行定义。 这可以在单独的源文件中完成,或者要感谢...

内联函数应在使用过的每个翻译单元中定义,并且在每种情况下都应具有完全相同的定义。

[N4431§7.1.2/ 4]

...作为标题中的inline函数。


在这种情况下,该标准甚至明确规定了定义的要求:

可以将析构函数声明为虚拟(10.3)或纯虚拟(10.4); 如果在程序中创建了该类的任何对象或任何派生类,则应定义析构函数。 [...]

[N4431§12.4/ 9]

是否可以创建无成员抽象基类?

最简单的方法是使析构函数成为纯虚拟的。

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

如果要多态删除该类的实例,则无论如何都必须具有虚拟析构函数。 这不仅是为了防止基类的实例化,还需要避免未定义的行为。 只要使其成为纯虚拟的即可。 并给它一个空的实现(是的,这在C ++中有效)。

但是,如果根本不使用多态,则应避免添加虚拟析构函数,而应仅使构造函数受保护。 请记住,基类不一定必须建立多态类层次结构(请参阅C ++库中的示例,如std::input_iterator_tag )。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM