Pure Virtual Function called error
I find this strange. In the ctor of Sample_Base, I call bar() which internally calls fun() which is a pure virtual function. I get the error "pure virtual function" called. Which is fine. Now, if I call fun() directly from Sample_Base's ctor, I don't get that error. I trie开发者_JS百科d it on VC++ 2010 Beta 2 and on g++ 4.4.1 on Ubuntu 9.10. I agree that giving an implementation for pure virtual function, other than pure virtual destructor, is meaningless. But, I am a bit surprised about this behaviour.
class Sample_Base
{
public:
Sample_Base()
{
bar();
// fun();
}
/* This is code does not throw any error.
Sample_Base()
{
fun();
}
*/
void bar()
{
fun();
}
virtual void fun() = 0;
virtual ~Sample_Base();
};
Sample_Base::~Sample_Base()
{
}
void Sample_Base::fun()
{
std::cout << "Sample_Base::fun\n";
}
class Sample_Derived : public Sample_Base
{
public:
Sample_Derived() : Sample_Base()
{
fun();
}
void fun()
{
std::cout << "Sample_Derived::fun\n";
}
~Sample_Derived()
{
}
};
When you call the function directly, since you are in the constructor, the compiler resolves the static type of your object (Sample_Base
) and calls Sample_Base::fun()
directly. Since you provided an implementation for it, the compiler finds the function and it works.
When you call it indirectly, through bar()
, the compiler must use the dynamic type, so it does a virtual call that gets resolved at runtime. And there it fails, because it calls a pure virtual function.
So the difference is in the moment it binds the function to the call.
Providing a definition for a pure virtual function is not necessarily meaningless. Marking a virtual function pure means that the enclosing class is abstract and that any class that derives from it is abstract unless the final override for that function is not a pure virtual function. A pure virtual function can still be called via an explicit non-virtual call.
In the body of a base class constructor (but not from a ctor-initializer) the version of a virtual function called through a virtual call is one defined in the class itself or one of its bases and not of any class overriding it (which would not yet have been constructed). This is specified explicitly in 12.7 [class.cdtor]/3.
It is legal to call a pure virtual function explicitly in a constructor body (i.e. using an explicit class qualifier) - although this would required the function to have a body defined - but it is undefined behaviour to call a pure virtual function via a virtual call which is only possible from the constructor or destructor of an abstract class. This is specified explicitly in 10.4 [class.abstract]/6.
At construction time, when the Sample_Base
constructor is called, the object is not fully constructed yet. Specifically the parts belonging to Sample_Derived
are not yet created calls to virtual functions that would be overwritten by Sample_Derived
will not call the implementation in Sample_Derived
, but the version defined in Sample_Base
. And since the function has no implementation there you get an error.
For more information and possible workarounds also see this entry in the C++ FAQ Lite.
Calling a virtual function won't call the overriding functions in the derived classes. Calling a pure virtual function in a constructor or destructor is Undefined behavior.
You might be interested in reading this and this.
This behavior is not undefined, it's explicitly defined: virtual functions are not virtual in constructors and destructors. They call the static version of the function. If the function is pure virtual, this results in the famous "pure virtual call" error in VC.
I've seen an amusing variation of this in a multithreaded program: an object is being destructed on thread A, while thread B is attempting to call a virtual function. There was no virtual function call in the constructor or destructor, but we still got hit with a pure virtual call error.
精彩评论