Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pure virtual function call interesting cases

Consider the following code:

#include <iostream>
using namespace std;

class A
{
  public:
   virtual void f() = 0;
   A(){f();}
};

void A::f() {
    cout<<"A"<<endl;
}

class B:public A{
 public:
    void f(){cout<<"B"<<endl;}
};
int main()
{
 B b;
}

In this case I directly call the virtual function from constructor and get compiler warning which says:
warning: abstract virtual 'virtual void A::f()' called from constructor.
But it executes without termination and prints A.

If I wrap the call of the function like this:

class A
{
  public:
   virtual void f() = 0;
   A(){g();}
   void g(){f();}
};

void A::f(){cout<<"A"<<endl;}

class B:public A{
 public:
    void f(){cout<<"B"<<endl;}
};
int main()
{
 B b;
}

The compiler does not output any warning during compilation but it crushes at runtime with the following message:

pure virtual method called   
terminate called without active exception   
Abort

Can anybody explain the behavior of both of this cases?

like image 354
Eduard Rostomyan Avatar asked Oct 20 '22 02:10

Eduard Rostomyan


1 Answers

§ 10.4 Abstract classes [class.abstract] / p6

Member functions can be called from a constructor (or destructor) of an abstract class; the effect of making a virtual call (10.3) to a pure virtual function directly or indirectly for the object being created (or destroyed) from such a constructor (or destructor) is undefined.

In brief: The effect of making a call to a pure virtual function directly or indirectly for the object being created from constructor is undefined.

A call to pure virtual member functions cannot be used from a constructor or a destructor, no matter if the call is direct or indirect, because then you end up with an undefined behavior.

The only useful example of providing the implementation of a pure virtual function is when calling it from a derived class:

struct A
{
    virtual void f() = 0;
};

void A::f()
{
    cout<<"A"<<endl;
}

struct B : A
{
    void f()
    {
        A::f();
        cout<<"B"<<endl;
    }
};
like image 93
Piotr Skotnicki Avatar answered Oct 22 '22 15:10

Piotr Skotnicki