When it is safe to call a virtual function in the constructor

I have code in which I really want to call a virtual method from the constructor. I know that this is considered unsafe, and I know enough about object construction to also understand why . I also do not experience these problems . My code is currently working, and I think everything should be fine, but I want to make sure.

That's what I'm doing:

I have a class hierarchy, and there is a regular public function that, as usual, just moves on to a private virtual method. However, I want to call this public method when building my objects, because it fills all the data into the object. I will be absolutely sure that this virtual call comes from a leaf class, because using this virtual method from any other part of the class hierarchy simply does not make sense.

So, in my opinion, the creation of the object should be completed when I make a virtual call, and everything should be fine. Is there anything that could go wrong? I think I will have to note this part of the logic with some remarks to explain why this logic should never be moved to any of the base clans, although it seems that it can be moved. But besides the stupidity of other programmers, I have to be fine, right?

+4
source share
3 answers

It is absolutely safe to call any non-abstract virtual function in the constructor or destructor! However, his behavior can be confusing, as he cannot do what is expected. Although the class constructor is executed, the static and dynamic type of the object is the type of constructor. That is, a virtual function will never be sent to redefine another derived class. In addition, virtual sending actually works: for example. when a virtual function is called using a pointer or a reference of a base class, it is correctly sent for redefinition in a class that is currently a constructor or destroyed. For example (possibly riddled with typos, as I currently cannot this code):

#include <iostream> struct A { virtual ~A() {} virtual void f() { std::cout << "A::f()\n"; } void g() { this->f(); } }; struct B: A { B() { this->g(); } // this prints 'B::f()' void f() { std::cout << "B::f()\n"; } }; struct C: B { void f() { std::cout << "C::f()\n"; } // not called from B::B() }; int main() { C c; } 

That is, you can directly or indirectly call a virtual function in the constructor or destructor of the class if you do not want the virtual function to be sent to another derived function. You can even do this, since a virtual function is abstract in a given class, if defined. However, when sending an abstract function undefined, a runtime error will occur.

+5
source

When the constructor is called, the class is set as an instance of this class, but not a derived class. You cannot call a virtual function of a derived class from a base constructor. When you get to the constructor of the derived class itself, all virtual functions should be safe to call.

If you want to make sure that someone cannot make the wrong call, define a virtual function in the base class and ask it to be approved and / or throw an exception when it is called.

+3
source

The rule is not so much that you need to be in a sheet class to understand that when you make a member call from Foo::Foo(..) , the object is exactly equal to Foo , even if it is on the path to a Bar (it is assumed that Foo obtained from Bar , and you instantiate Bar ). It is 100% more reliable.

Otherwise, the fact that the member is virtual is not so significant. There are other errors that happen exactly the same with non-virtual functions: if you were to call a virtual or non-virtual method, which assumed that the object was completely constructed, but called it inside the constructor, before that was the case, you also have problems. These are just hard cases to disable them, because not only the function that you call is all right, all the functions that it calls should be in order.

It doesn't seem like you have a problem, this is just one of those places that are error prone.

+1
source

Source: https://habr.com/ru/post/1392142/


All Articles