I have an abstract base class, which serves the purpose of allowing an array of pointers to a base class to be created. (Useful for 'many things'...)
My abstract base class contains no member functions. Therefore there are no pure virtual methods, and therefore I guess it is not technically abstract.
However, I do not want to be able to create an instance of this class.
Is it possible to create a memberless abstract base class? If not, is there another resolution to preventing an instance of my "abstract base" from being created? Will making the constructor protected
suffice?
It has been pointed out to me that actually, an abstract base class would not be required if the purpose of that class was to allow a vector or array of pointers to the base class to be created - one could simply not have a base class and use as the base class the class at the top of the inheritance hierarchy. Alternatively, one could copy and paste that top class and exchange the implemented methods for pure virtual functions with no implementation, however this seems logically inconstant with the idea of abstract base pointers, and would lead to more difficult to maintain code.
Provide a pure virtual destructor:
struct Base {
virtual ~Base() = 0;
};
inline Base::~Base() {}
You need to provide an implementation, which you could right in the header by making it inline
.
An abstract class is a class with some pure virtual function:
[...] A class is abstract if it has at least one pure virtual function. [...]
[N4431 §10.4/2]
Since you want an array of pointers to instances of (classes derived from) your abstract class, I assume you also want to be able to eventually delete
and thus destruct one or more of those instances via these pointers:
Base * instance = // ... whatever ...
delete instance;
To call the correct destructor (of the derived class) in that case, the destructor has to be virtual.
So since it's virtual either way, and you don't want some pure virtual member function, it's best to make the destructor pure virtual.
To make a virtual function pure, you append the pure-specifier to its declaration:
struct Foo {
virtual void bar(void) /* the */ = 0; // pure-specifier
};
Now, regarding the definition, you wonder why we need to provide one, since ...
[...] 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]
This is because when destructing a derived class, after the derived classes destructor has been called, the destructors of the bases classes will also be called:
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]
So a definition of the pure virtual destructor if the Base
class is needed. However ...
[...] A function declaration cannot provide both a pure-specifier and a definition [...]
[N4431 §10.4/2]
... so it has to be defined outside of the class definition. This could be done in a separate source file, or thanks to ...
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]
... as a inline
function in the header.
The standard is even explicit about the requirement of a definition in this case:
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]