From 10.4 Abstract Classes parag. 6 in the Standard :
\"Member functions can be called from a constructor (or destructor) of an abstract class; the effe
Before discussing why it's undefined, let's first clarify what the question is about.
#include
using namespace std;
struct Abstract {
virtual void pure() = 0;
virtual void impure() { cout << " Abstract :: impure() " << endl; }
Abstract() {
impure();
// pure(); // would be undefined
}
~Abstract() {
impure();
// pure(); // would be undefined
}
};
struct X : public Abstract {
virtual void pure() { cout << " X :: pure() " << endl; }
virtual void impure() { cout << " X :: impure() " << endl; }
};
int main() {
X x;
x.pure();
x.impure();
}
The output of this is:
Abstract :: impure() // called while x is being constructed
X :: pure() // x.pure();
X :: impure() // x.impure();
Abstract :: impure() // called while x is being destructed.
The second and third lines are easy to understand; the methods were originally defined in Abstract, but the overrides in X take over. This result would have been the same even if x
had been a reference or pointer of Abstract type instead of X type.
But this interesting thing is what happens inside the constructor and destructor of X. The call to impure()
in the constructor calls Abstract::impure()
, not X::impure()
, even though the object being constructed is of type X
. The same happens in the destructor.
When an object of type X
is being constructed, the first thing that is constructed is merely an Abstract
object and, crucially, it is ignorant of the fact that it will ultimately be an X
object. The same process happens in reverse for the destruction.
Now, assuming you understand that, it is clear why the behaviour must be undefined. There is no method Abstract :: pure
which could be called by the constructor or destructor, and hence it wouldn't be meaningful to try to define this behaviour (except possibly as a compilation error.)
Update: I've just discovered that is possible to give an implementation, in the virtual class, of a pure virtual method. The question is: Is this meaningful?
struct Abstract {
virtual void pure() = 0;
};
void Abstract :: pure() { cout << "How can I be called?!" << endl; }
There will never be an object whose dynamic type is Abstract, hence you'll never be able to execute this code with a normal call to abs.pure();
or anything like that. So, what is the point of allowing such a definition?
See this demo. The compiler gives warnings, but now the Abstract::pure()
method is callable from the constructor. This is the only route by which Abstract::pure()
can be called.
But, this is technically undefined. Another compiler is entitled to ignore the implementation of Abstract::pure
, or even to do other crazy things. I'm not aware of why this isn't defined - but I wrote this up to try to help clear up the question.