Any C ++ implementation must call a function implementation declared at the level of the current class in the hierarchy in the constructor or destructor.
Excerpt from CPP FAQ :
[...]
In the constructor, it hasn’t happened. Objects are constructed from the base up, “base before derived”.
[...]
This is a “derived class before the base class”.
In a nutshell, in the constructor, virtual functions do not work because the target object is not yet constructed, but in destructors because the target object is already destroyed.
Three options come to my mind how to fix it.
1) Parameterize the function, and pass it all the necessary
#include <iostream> #include <string> class Base{ public: Base(const std::string &str){ createView(str); } void createView(const std::string &str){ std::cout << str << "\n"; } virtual ~Base() = default; }; class Derived : public Base{ public: Derived() : Base("Derived View") {} }; int main(){ Base *p = new Derived(); delete p; }
The bottom line: no virtual functions - no problem.
2) Factory method
#include <iostream> class Base{ public: template<class T> static T* construct(){ T *t = new T; t->createView(); return t; } virtual void createView(){ std::cout << "Base View\n"; } virtual ~Base() = default; }; class Derived : public Base{ public: virtual void createView() override{ std::cout << "Derived View\n"; } }; int main(){ Base *p = Base::construct<Derived>(); delete p; }
Essence: instead of the constructor, we use the construct method, which first creates the entire object, and only then starts calling virtual functions.
3) Envelope / Letter
#include <iostream> #include <memory> class Base{ public: Base() = default; virtual void createView(){ std::cout << "Base View\n"; } virtual ~Base() = default; }; class Derived : public Base{ public: Derived() : Base() {} void createView() override{ std::cout << "Derived View\n"; } }; template<class Letter> class Envelope : public Base{ std::unique_ptr<Letter> _letter; public: Envelope(): Base(), _letter(new Letter) { _letter->createView(); } void createView() override{ _letter->createView(); } ~Envelope(){} }; int main(){ Base *p = new Envelope<Derived>(); delete p; }
Essence: the same factory method in the form of a class. The Envelope keeps a letter of Derived inside it and delegates to it all calls to virtual functions.
Derivedclass function when yourBasehas not been created yet? See the good rule - Bogdan