Why is this not a call of a pure virtual function?

780 views Asked by At

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?

2

There are 2 answers

4
Angew is no longer proud of SO On BEST ANSWER

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 a dynamic_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.

1
Bathsheba On

The statement B b; calls the default constructor to B.

When constructing B, nothing pertinent to B is constructed until A is fully constructed.

So in attempting to call callFoo(), the behaviour is undefined since you cannot rely on the v-table for class B being set up.

In summary: the behaviour of calling a pure virtual function during the construction of an abstract class is undefined.