C++:如果 class 没有成员函数,如何创建抽象基础 class?
C++: How to create an abstract base class if class has no member functions?
我有一个抽象基 class,它的目的是允许创建指向基 class 的指针数组。 (对 'many things'...有用)
我的抽象基 class 不包含任何成员函数。因此没有纯虚方法,因此我猜它在技术上不是抽象的。
但是,我不想创建这个 class 的实例。
是否可以创建无成员抽象基 class?如果没有,是否有其他解决方案来阻止创建 my "abstract base" 的实例?构造函数 protected
就足够了吗?
有人向我指出,实际上,如果 class 的目的是允许指向基 class 的向量或指针数组,则不需要抽象基 class =25=] 被创建 - 可以简单地没有基础 class 并使用继承层次结构顶部的 class 作为基础 class。或者,可以复制并粘贴 top class 并将已实现的方法替换为没有实现的纯虚函数,但这在逻辑上似乎与抽象基指针的想法不一致,并且会导致代码更难维护。
提供纯虚析构函数:
struct Base {
virtual ~Base() = 0;
};
inline Base::~Base() {}
您需要提供一个实现,您可以在 header 中将其设置为 inline
。
一个抽象 class 是一个带有一些纯虚函数的 class:
[...] A class is abstract if it has at least one pure virtual function. [...]
[N4431 §10.4/2]
因为你想要一个指向实例的指针数组(classes 派生自)你的抽象 class,我假设你也希望最终能够 delete
从而通过这些指针销毁 一个或多个实例:
Base * instance = // ... whatever ...
delete instance;
在这种情况下调用正确的析构函数(派生的 class),析构函数 必须 是虚拟的。
所以既然它是虚拟的,而且你不想要一些纯虚拟的成员函数,最好使析构函数成为纯虚拟的。
要使虚函数成为纯虚函数,请将 pure-specifier 附加到它的声明中:
struct Foo {
virtual void bar(void) /* the */ = 0; // pure-specifier
};
现在,关于定义,您想知道为什么我们需要提供一个,因为...
[...] A pure virtual function need be defined only if called with, or as if with (12.4), the qualified-id syntax (5.1). [...]
[N4431 §10.4/2]
这是因为在析构派生class时,派生classes的析构函数被调用后,基础classes的析构函数也会被调用:
struct Derived : public Base {
~Derived() {
// contents
// Base::~Base() will be called
}
};
After executing the body of the destructor [...] a destructor for class X calls [...] the destructors for X’s direct base classes and, if X is the type of the most derived class (12.6.2), its destructor calls the destructors for X’s virtual base classes. All destructors are called as if they were referenced with a qualified name [...]
[N4431 §12.4/8]
所以如果 Base
class 需要纯虚拟析构函数的定义。然而...
[...] A function declaration cannot provide both a pure-specifier and a definition [...]
[N4431 §10.4/2]
... 所以它必须在 class 定义之外定义。这可以在单独的源文件中完成,或者感谢 ...
An inline function shall be defined in every translation unit in which it is odr-used and shall have exactly the same definition in every case [...]
[N4431 §7.1.2/4]
... 作为 header.
中的 inline
函数
在这种情况下,标准甚至明确要求定义:
A destructor can be declared virtual (10.3) or pure virtual (10.4); if any objects of that class or any derived class are created in the program, the destructor shall be defined. [...]
[N4431 §12.4/9]
Is it possible to create a memberless abstract base class?
最简单的方法是使析构函数成为纯虚拟的。
class AbstractBase
{
public:
virtual ~AbstractBase() = 0;
};
如果您要以多态方式删除那个 class 的实例,那么无论如何您 必须 有一个虚拟析构函数。这不仅仅是为了防止基 class 的实例化, 需要 来避免未定义的行为。只是让它纯虚拟。并给它一个空的实现(是的,这在 C++ 中有效)。
但是,如果您根本不使用多态性,那么您应该避免添加虚拟析构函数,而只是使构造函数受保护。请记住,基础 class 不一定必须建立多态 class 层次结构(请参阅 C++ 库中的示例,例如 std::input_iterator_tag
)。
我有一个抽象基 class,它的目的是允许创建指向基 class 的指针数组。 (对 'many things'...有用)
我的抽象基 class 不包含任何成员函数。因此没有纯虚方法,因此我猜它在技术上不是抽象的。
但是,我不想创建这个 class 的实例。
是否可以创建无成员抽象基 class?如果没有,是否有其他解决方案来阻止创建 my "abstract base" 的实例?构造函数 protected
就足够了吗?
有人向我指出,实际上,如果 class 的目的是允许指向基 class 的向量或指针数组,则不需要抽象基 class =25=] 被创建 - 可以简单地没有基础 class 并使用继承层次结构顶部的 class 作为基础 class。或者,可以复制并粘贴 top class 并将已实现的方法替换为没有实现的纯虚函数,但这在逻辑上似乎与抽象基指针的想法不一致,并且会导致代码更难维护。
提供纯虚析构函数:
struct Base {
virtual ~Base() = 0;
};
inline Base::~Base() {}
您需要提供一个实现,您可以在 header 中将其设置为 inline
。
一个抽象 class 是一个带有一些纯虚函数的 class:
[...] A class is abstract if it has at least one pure virtual function. [...]
[N4431 §10.4/2]
因为你想要一个指向实例的指针数组(classes 派生自)你的抽象 class,我假设你也希望最终能够 delete
从而通过这些指针销毁 一个或多个实例:
Base * instance = // ... whatever ...
delete instance;
在这种情况下调用正确的析构函数(派生的 class),析构函数 必须 是虚拟的。
所以既然它是虚拟的,而且你不想要一些纯虚拟的成员函数,最好使析构函数成为纯虚拟的。
要使虚函数成为纯虚函数,请将 pure-specifier 附加到它的声明中:
struct Foo {
virtual void bar(void) /* the */ = 0; // pure-specifier
};
现在,关于定义,您想知道为什么我们需要提供一个,因为...
[...] A pure virtual function need be defined only if called with, or as if with (12.4), the qualified-id syntax (5.1). [...]
[N4431 §10.4/2]
这是因为在析构派生class时,派生classes的析构函数被调用后,基础classes的析构函数也会被调用:
struct Derived : public Base {
~Derived() {
// contents
// Base::~Base() will be called
}
};
After executing the body of the destructor [...] a destructor for class X calls [...] the destructors for X’s direct base classes and, if X is the type of the most derived class (12.6.2), its destructor calls the destructors for X’s virtual base classes. All destructors are called as if they were referenced with a qualified name [...]
[N4431 §12.4/8]
所以如果 Base
class 需要纯虚拟析构函数的定义。然而...
[...] A function declaration cannot provide both a pure-specifier and a definition [...]
[N4431 §10.4/2]
... 所以它必须在 class 定义之外定义。这可以在单独的源文件中完成,或者感谢 ...
An inline function shall be defined in every translation unit in which it is odr-used and shall have exactly the same definition in every case [...]
[N4431 §7.1.2/4]
... 作为 header.
中的inline
函数
在这种情况下,标准甚至明确要求定义:
A destructor can be declared virtual (10.3) or pure virtual (10.4); if any objects of that class or any derived class are created in the program, the destructor shall be defined. [...]
[N4431 §12.4/9]
Is it possible to create a memberless abstract base class?
最简单的方法是使析构函数成为纯虚拟的。
class AbstractBase
{
public:
virtual ~AbstractBase() = 0;
};
如果您要以多态方式删除那个 class 的实例,那么无论如何您 必须 有一个虚拟析构函数。这不仅仅是为了防止基 class 的实例化, 需要 来避免未定义的行为。只是让它纯虚拟。并给它一个空的实现(是的,这在 C++ 中有效)。
但是,如果您根本不使用多态性,那么您应该避免添加虚拟析构函数,而只是使构造函数受保护。请记住,基础 class 不一定必须建立多态 class 层次结构(请参阅 C++ 库中的示例,例如 std::input_iterator_tag
)。