Here you need to achieve about this. So that the base class in the constructor calls a redefined function. Who will help to somehow implement such code so that polymorphism worked.

class Base { public: Base() { createView(); } virtual void createView() { std::cout << "Base View\n"; } }; class Derived : public Base { public: Derived() : Base() { } virtual void createView() override { std::cout << "Derived View\n"; } }; int main() { Base *p = new Derived(); // cout Derived View getchar(); return 0; } 
  • It is a bad idea to call virtual functions in a constructor. How do you want to call a Derived class function when your Base has not been created yet? See the good rule - Bogdan
  • I know what a bad idea is but need. Any ideas how to implement something like this? - Artur Lazian
  • From the same place: “There are different solutions to this problem. One of them is to make the logTransaction function non-virtual in the Transaction class, then require that the constructors of the derived class pass the information necessary for writing to the protocol to the Transaction constructor. This function can then safely call non-virtual logTransaction” . Translating, in your case : make the function non-virtual, and pass it the necessary information as a parameter. - Bogdan
  • Is this a xy task? What for ? - Harry

1 answer 1

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.

  • "in the constructor, virtual functions do not work" ... You first said correctly: "I must call in the constructor or destructor the implementation of the function declared at the level of the current class in the hierarchy." Virtual functions and the virtual mechanism in the constructor work , but only up to the current level of the hierarchy, not lower. Overrides made below in the hierarchy are ignored. - AnT
  • @AnT, what do you mean by "virtual mechanism in constructor work" ? Those. it is clear that the most derived standard is written, but in practice there will be no dynamic resolution, i.e. vptr will not be used, which means no virtuality. - ixSci 5:09
  • @ixSci: First, the only way to suppress virtuality in C ++ is to use a qualified method name in a call. In all other cases, the call to the virtual method is an ordinary virtual call. If the compiler does not use vptr in a virtual call, it is nothing more than optimization based on the fact that the compiler was able to unambiguously predict where vptr will lead. This optimization is usually used only if the virtual method is called directly from the constructor. - AnT
  • one
    @ixSci: Once again: what are "calls in constructors / destructors"? Here is an example: struct B { virtual void foo() {} void bar() { foo(); } }; struct D : B { virtual void foo() {} D() { bar(); } }; struct DD : D { virtual void foo() {} }; struct B { virtual void foo() {} void bar() { foo(); } }; struct D : B { virtual void foo() {} D() { bar(); } }; struct DD : D { virtual void foo() {} }; From the constructor DD::DD() constructor D::D() called. During constructor D::D() , the method B::bar() called. From the B::bar() method, the foo() method is called. The control falls into D::foo() , not B::foo() . This is a classic virtuality that worked during the construction of the D::D() constructor. - AnT
  • one
    But D::foo() was called, but not DD::foo() - this is the depth limit I’m talking about. Virtuality, as you can see, is and works great. It does not work as the newbies naively expect, but their expectations are completely unjustified - no one has ever promised them such virtuality. For some reason you conclude from this that "virtuality in the constructor does not work." This is a strange conclusion. This is about how to expect that buying a powerful telescope you can see green men on Mars. And, having failed to see them there, to come to the conclusion that the telescope "does not work." - AnT