Pure virtual function called error

I find it strange. In ctor Sample_Base, I call bar (), which internally calls fun (), which is a pure virtual function. I get a "pure virtual function" error message. This is normal. Now, if I call fun () directly from the Sample_Base ctor, I do not get this error. I tried this on VC ++ 2010 Beta 2 and on g ++ 4.4.1 on Ubuntu 9.10. I agree that providing an implementation of a pure virtual function other than a pure virtual destructor does not make sense. But I'm a little surprised by this behavior.

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() { } }; 
+6
c ++
source share
5 answers

When you call a 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 it with an implementation, the compiler finds the function and works.

When you call this indirectly through bar() , the compiler must use a dynamic type, so it makes a virtual call that resolves at runtime. And there he fails because he calls a pure virtual function.

Thus, the difference at the moment the function is bound to the call.

+6
source share

Providing a definition for a pure virtual function is not necessarily meaningless. Marking a pure virtual function means that the enclosing class is abstract and that any class that derives from it is abstract if the final override for this 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 the constructor of the base class (but not from the ctor initializer), the version of the virtual function that is called through the virtual call is defined in the class itself or in one of its bases, and not in the class that overrides it (which has not yet been built). This is explicitly stated in 12.7 [class.cdtor] / 3.

It is legal to uniquely call a pure virtual function in the constructor body (i.e. using an explicit classifier) ​​- although this would require the function to have a specific body, undefined behavior calls a pure virtual function through a virtual call, which is possible only from the constructor or destructor abstract class. This is explicitly stated in 10.4 [class.abstract] / 6.

+4
source share

A call to a virtual function will not call override functions in derived classes. Calling a pure virtual function in a constructor or destructor is Undefined behavior .

You may be interested in reading this and this.

+1
source share

At the time of construction, when the Sample_Base constructor is Sample_Base , the object is not yet fully constructed. In particular, parts related to Sample_Derived have not yet been created, calls to virtual functions that will be overwritten by Sample_Derived will not call the implementation in Sample_Derived , and the version defined in Sample_Base . And since the function has no implementation, you get an error message.

For more information and possible workarounds, also see this entry in the C ++ FAQ Lite .

+1
source share

This behavior is not undefined, it is 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 a known β€œpure virtual call” error in VC.

I saw a funny change to this in a multi-threaded program: an object is destroyed in thread A, and thread B is trying to call a virtual function. There was no virtual function call in the constructor or destructor, but we still ended up with a pure virtual call error.

+1
source share

All Articles