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]