Call to Pure Virtual Function from Base Class Constructor

call to pure virtual function from base class constructor

There are many articles that explain why you should never call virtual functions in constructor and destructor in C++. Take a look here and here for details what happens behind the scene during such calls.

In short, objects are constructed from the base up to the derived. So when you try to call a virtual function from the base class constructor, overriding from derived classes hasn't yet happened because the derived constructors haven't been called yet.

Calling pure virtual function in constructor gives an error

Calling virtual functions in a constructor is recognised as a bad thing to do.

During base class construction of a derived class object, the type of
the object is that of the base class. Not only do virtual functions
resolve to the base class, but the parts of the language using runtime
type information (e.g., dynamic_cast (see Item 27) and typeid) treat
the object as a base class type.

So your instantiation of b invokes the a constructor. That calls foo(), but it's the foo() on a that gets called. And that (of course) is undefined.

Calling Pure Virtual Function From Abstract Base Class Member Function?

Func is calling the virtual ones, not the pure virtual ones. You would have to qualify the calls with a scope operator, i.e. AbstractClass::Step1() to call THAT (virtual pure) function. Since you are not, you will always get an implementation by a derived class.

how to call pure virtual function from base class if that function is defined in more than 2 derived class

The whole point of pure virtual functions is to actually decouple the concrete implementation from the abstract base class interface.

If you are calling the pureFunc() through a Base* pointer or reference, the calling code should be agnostic about the implementations in D1 and D2, and thus shouldn't need to know which one is actually called.

Calling virtual functions inside constructors

Calling virtual functions from a constructor or destructor is dangerous and should be avoided whenever possible. All C++ implementations should call the version of the function defined at the level of the hierarchy in the current constructor and no further.

The C++ FAQ Lite covers this in section 23.7 in pretty good detail. I suggest reading that (and the rest of the FAQ) for a followup.

Excerpt:

[...] In a constructor, the virtual call mechanism is disabled because overriding from derived classes hasn’t yet happened. Objects are constructed from the base up, “base before derived”.

[...]

Destruction is done “derived class before base class”, so virtual functions behave as in constructors: Only the local definitions are used – and no calls are made to overriding functions to avoid touching the (now destroyed) derived class part of the object.

EDIT Corrected Most to All (thanks litb)

(Why) Is virtual base class constructor call required in pure virtual derived class?

Design issues (which clearly exist here) aside, I fully agree with your reasoning that, because Left is an abstract class, no Left constructor will ever have to call any Base constructor and thus it is odd that it is required.

In fact, I tested your code with several compiler versions and it does compile just fine with gcc 7.1 and onwards, with clang 3.4.1 and onwards, and with all available msvc versions.

So, my assumption is, that this was just a bug in earlier compiler versions. Can anyone confirm this?

Also note, if you change virtual void leftsMethod() = 0; to virtual void leftsMethod() {}, so that Left is not abstract anymore, the error returns, even with the latest versions. And this makes perfectly sense, as now you could instantiate a Left instance and thus it would be up to Left's constructor to call one of Base's constructors.

Possible workaround

If you cannot switch to a newer compiler and if you cannot alter the implementation of Base, this may be a working solution for you:

Define a dummy instance of CustomType somewhere. Then, you can provide the "required" default constructors like this:

class CustomType{};

class Base
{
public:
Base( CustomType& obj ) : refObj_( obj ) {}
private:
CustomType& refObj_;
};

static CustomType dummy;

class Left : public virtual Base
{
protected:
Left() : Base(dummy) {}; // note here
public:
virtual void leftsMethod() = 0;
};

class Right : public virtual Base
{
protected:
Right() : Base(dummy) {}; // and here
public:
virtual void rightsMethod() = 0;
};

class Bottom : public Left, public Right
{
public:
Bottom( CustomType& obj ) : Base( obj ), Left(), Right() {}
virtual void leftsMethod() override {}
virtual void rightsMethod() override {}
};

void test()
{
CustomType c;
Bottom b(c);
}

This is just to make the compiler happy, your argument that these constructors will never call Base(dummy) still holds.

Note however, that Base should really have a virtual destructor! I don't know if you just didn't include it here for brevity or if it really doesn't have one. If it doesn't, it's a very bad idea to build a class hierarchy on top of it.

function called by constructors of derived classes not supposed to be pure virtual in base class

Instead of forcing them to call a function (which you anyway cannot guarantee), make the base class constructor expect a parameter that includes the behavior you need to have.

That way, the base class is self-contained and has all the required information by the time its constructor runs.


For example, if you were thinking of something like this:

class Base
{
public:
Base()
{
reset();
}

protected:
virtual void reset() = 0;
void setValue(int value);
};

class Derived : public Base
{
public:
void reset() override
{
setValue(20);
}
};

you can do this instead:

class Base
{
public:
explicit Base(int value)
{
setValue(value);
}

private: // can be private
void setValue(int value);
};

class Derived : public Base
{
public:
Derived()
: Base(20)
{
}
};

C++ calling pure virtual function from non virtual function in base class

I am aware that you can / should not call virtual functions in the constructor and that a pure virtual destructor is not possible.

Declaring a function pure virtual does not mean that you cannot provide an implementation for it. This applies to destructors as well:

struct Foo {
virtual ~Foo() = 0;
...
};
Foo::~Foo() {
... // Implement destructor
}

The clang compiler then gives me a linker error

Undefined symbols for architecture x86_64:
"Base::bar() const", referenced from:

This usually happens when you incorrectly compile your classes one-by-one, and then do not link them properly. The compiler has a simple way to compile all classes together, and link the results, as follows:

g++ base.cpp child.cpp main.cpp

Note that you need to include headers for the classes in their implementation files, for example

#include "base.h"

int Base::bar() {
return this->foo()*3;
}

Make sure that you fix any errors that come up in the process (hint: the above will produce an error).



Related Topics



Leave a reply



Submit