I tried to "repair" the example in this answer as to demonstrate how a pure virtual function can be called.
#include <iostream>
using namespace std;
class A
{
int id;
public:
A(int i): id(i) {}
int callFoo() { return foo(); }
virtual int foo() = 0;
};
class B: public A
{
public:
B(): A(callFoo()) {}
int foo() { return 3; }
};
int main() {
B b; // <-- this should call a pure virtual function
cout << b.callFoo() << endl;
return 0;
}
But I get no runtime error here (with C++ 4.9.2), but the output 3. I tried the same with Borland C++ 5.6.4, but there I'm getting an access violation. I think that foo()
should be pure virtual in the call of the constructor of the base class.
Who is wrong? Should I try more compilers? Am I right in my understanding of virtual functions?
Pure virtual functions must not be called from a C++ constructor. As a general rule, you should never call any kind of virtual function in a constructor or destructor because those calls will never go to a more derived class than the currently executing constructor or destructor.
You may call a virtual function as long as it is not a pure virtual function, and as long as you know that what you are calling is the method from the class itself and not expecting any polymorphism. Calling a pure virtual function from a constructor is undefined behaviour even if it has an implementation.
A pure virtual function is a virtual function in C++ for which we need not to write any function definition and only we have to declare it. It is declared by assigning 0 in the declaration. An abstract class is a class in C++ which have at least one pure virtual function.
Your code has Undefined Behaviour: it is UB to call a member function on an object (even a non-virtual one) before all of its base classes have been initialised. C++14 (n4140) 12.6.2/14, emphasis mine:
Member functions (including virtual member functions, 10.3) can be called for an object under construction. Similarly, an object under construction can be the operand of the
typeid
operator (5.2.8) or of adynamic_cast
(5.2.7). However, if these operations are performed in a ctor-initializer (or in a function called directly or indirectly from a ctor-initializer) before all the mem-initializers for base classes have completed, the result of the operation is undefined. ...
ctor-initializer is the entire list following :
. mem-initializer is one element of this list.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With