Help to deal with inheritance and virtual functions. There is such a class:
.h -

#ifndef CUSTOMSUBWINDOW_H #define CUSTOMSUBWINDOW_H #include <QMdiSubWindow> class CustomSubWindow : public QMdiSubWindow { public: explicit CustomSubWindow(QWidget *parent = 0); virtual void createUI(); }; #endif // CUSTOMSUBWINDOW_H 

.cpp -

 #include "CustomSubWindow.h" CustomSubWindow::CustomSubWindow(QWidget *parent) :QMdiSubWindow(parent) { createUI(); } void CustomSubWindow::createUI() { } 

There is a heir class:
.h -

 #ifndef CAT_PRODUCTS_H #define CAT_PRODUCTS_H #include <CustomSubWindow.h> class CatProducts : public CustomSubWindow { Q_OBJECT public: explicit CatProducts(QWidget *parent = 0); void createUI(); }; #endif // CAT_PRODUCTS_H 

.srr-

 #include "CatProducts.h" CatProducts::CatProducts(QWidget *parent) : CustomSubWindow(parent) { } void CatProducts::createUI() { setWindowTitle("Справочник товаров!!!"); } 

Those. in the successor, we override the createUI() method, which is called in the constructor of the base class. As I understand it, you need to use late binding, i.e. declare the method virtual. But it does not work. What am I wrong?

    4 answers 4

    When a derived class object is created, the base class constructor is first called.
    At this moment, there is still NO object of the derived class, therefore the call to the virtual function and the later binding are impossible - only the functions of the class being created are called.

    In the constructor, virtuality does not work and cannot work: think for yourself how the base class constructor can know whether it was called to create an object of the base class or an object of some of the derived classes (which were not in the project at the time of writing the base class). .)?

    • Thank you. Why is this not written in textbooks? - Artik
    • one
      @Artik ,, write. “The C ++ Programming Language 4th ed.” 20.3.2 and 22.4 - ixSci
    • 3
      "In the constructor, virtuality does not work and cannot work ...". In the constructor, virtuality works and works the same way as always: the choice of a specific function for a call is made based on the dynamic type of the object. Just do not forget that during the operation of the class A constructor, the dynamic type of the constructed object is A Therefore, virtuality in the hierarchy works from the root of the hierarchy and down to type A , but not lower. As long as we do not “rest” on type A, virtuality works in the “usual” way. - AnT
    • one
      @ixSci: Well, this part is understandable, but I still would not call this behavior safe. If the programmer believes that the function is called, but in reality it is not called in some cases (and there is no chance to see the problem when there is an indirect challenge), then this is the road to problems. - VladD
    • one
      @AnT This is probably not a virtuality, because, as I understand it, late binding does not work here. Calls are resolved at compilation, not via vtable. - Harry

    By definition, calls to virtual methods in C ++ are associated with a specific implementation of a method based on the analysis of the dynamic type of the object used in such a call. This is where they differ from non-virtual calls that are based on a static object type.

    So, in C ++, during the direct work of the constructor (or destructor) of class A dynamic type of the constructed object is assumed to be exactly A That is, even if a constructed object of type A is the base subobject of some object of a class of successor B , the dynamic type of the constructed object during the operation of the constructor A is exactly A Only when the constructor of class A finishes its work and transfers control to the constructor of class B will the dynamic type of the constructed object magically change and become B

    This means that all virtual mechanisms during the activity of class A constructor continue to work as usual, but their functionality will be limited to class A from below: virtual functions will be selected only from class A and classes located higher in the hierarchy (ancestor classes of class A ), but not from classes located down the hierarchy (not from heir classes).

    That is what you are watching.

    PS The assertions that virtual calls made from the constructor supposedly “do not work” or “behave as non-virtual” do not correspond to reality. Virtual methods behave as always - in full accordance with the dynamic type of the constructed object. The illusion of "non-virtual" arises only because of the triviality and non-demonstrativeness of the example under consideration: the class making the virtual call has no ancestors at all.

    • one
      This would be a reference to the standard add to secure the rightness so to speak. - αλεχολυτ
    • Thanks, available. - Artik
    • one
      Illusion, not illusion, what's the difference? Non-polymorphic behavior and everything. What, in fact, made the author ask a question - the function behaves differently than the user expected. Therefore, both answers that you have indicated as “not corresponding to reality” correspond to this. - ixSci

    In C ++, virtual functions behave like non- virtual when called from a constructor or destructor.

      In support of the final comment from the @AnT answer, a small replicating example:

       class First { public: virtual void Report() { cout << "First" << endl; } void CallReport() { Report(); } }; class Second : public First { public: virtual void Report() { cout << "Second" << endl; } Second() { CallReport(); } }; class Third : public Second { public: virtual void Report() { cout << "Third" << endl; } }; int main() { Third third; return 0; } 

      http://ideone.com/zOsWbO

      This example displays Second . The CallReport function calls the virtual Report method. In the Second constructor, the object type is Second , and the virtual call is resolved in Second::Report .

      • But if I understand correctly, there is no late binding ... - Mikhailo
      • @Mikhailo: How not? And where CallReport method at compile time know from what it needs to call Second::Report ? - VladD