Solve C ++ virtual functions from a base class

Sorry, if this is a fraud, I can not find the answer completely right.

I want to call a function from an element of the base class and enable it for the version of the subclass. I thought that declaring it virtual would do it, but it is not. Here is my approach:

class GUIWindow { public: GUIWindow() { SetupCallbacks(); } virtual void SetupCallbacks() { // This function always called } }; class GUIListbox : public GUIWindow { public: void SetupCallbacks() { // This never called } }; GUIListbox lb; // GUIWindow::SetupCallbacks is called :( 

What am I doing wrong?

Many thanks

Si

+4
source share
5 answers

When you call virtual functions when building some class C (i.e., when the C constructor is active), the virtual mechanism works, but it works in a restricted mode. The resolution of virtual calls in the class hierarchy is limited to the class that is currently being built ( C ). This means that virtual calls will be solved as if class C was the "final" class in the hierarchy, as if it had no descendants.

The same is true for destructors.

In your example, you are calling a virtual function from the constructor of the GUIWindow class. As long as the GUIWindow constructor GUIWindow active, its virtual mechanism will work as if there were no other classes derived from GUIWindow . This mechanism completely ignores the existence of the GUIListbox class. This is why virtual call resolution โ€œstopsโ€ on the GUIWindow and calls GUIWindow::SetupCallbacks , as if GUIListbox::SetupCallbacks did not exist.

You can read the information in the C ++ FAQ http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.5

+3
source

Your derived type has not yet been created.

 Class Cat : Animal { //... }; 

When you create a Cat object creation, the following happens:

  • Build an animal
  • Construct cat

When your object goes out of scope or is destroyed with delete, if on the heap, the following happens:

  • Destroy cat
  • Destroy animals

For this reason, you should not call virtual functions in your constructor or destructor. You would even have a pure virtual function call if you did not have an implementation in your base class.

You need:

 GUIListbox lb; lb.SetupCallbacks(); 

The point of the virtual is that you can do things like:

 GuiWindow *lb = new GuiListbox(); lb->SetupCallback();//Gets correctly resolved to GuiListBox version 
+1
source

The problem is that you are trying to call the constructor virtual function construct. The constructor of the base class is called before the constructor of the derived class, so the "derived parts" of the object are not yet created when the constructor of the base classes is launched.

An object will behave as an object of the base class type until the constructor of the base classes completes and starts the constructor of the derived classes. This means that calls to virtual functions will not call implementations defined in the derived class, they will simply execute the version from the base class.

Also see the C ++ FAQ lite for more details and possibly workarounds .

0
source

Quick answer: you may need to declare a constructor in the GUIListbox that calls SetupCallbacks . The reason is more complicated: since GUIListbox does not declare a constructor, when you declare an object of this type, the GUIWindow constructor is GUIWindow . When the GUIWindow constructor GUIWindow started, the object is not yet a GUIListbox. From the point of view of the compiler, it becomes a GUIListbox only after starting the (empty) constructor for this class. Therefore, when the first constructor starts, methods from the GUIWindow are called. IOW, this does not work and will never work in C ++ the way you want.

Here is a link detailing this trap: http://www.artima.com/cppsource/nevercall.html .

And here is the explanation from my favorite C ++ resource: http://yosefk.com/c++fqa/inheritance-mother.html#fqa-23.5

-1
source

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


All Articles