Correct wording of virtual inheriting class constructors in C + +

Source: Internet
Author: User

The recent work of a software feature has been degraded, traced down to find that a class member variable is not properly initialized. This problem is related to the syntax of a derived class constructor in the case of a virtual inheritance of C + +. Here is a description of the cause of the error, hoping to help more people.

The inheritance structure of the classes with virtual inheritance in our code is not the same as the classic diamond structure in the textbook. Inheritance from Intermediate1 and Intermediate3 to Base2 is a virtual inheritance. Both Base1 and Base2 contain member variables and provide the appropriate constructors to accept the specified initialization value. BASE2 also has a default constructor that initializes its member variables to 0. intermediate1,2,3 also provides a constructor that takes the specified initialization value and calls Base1 and Base2 constructors in the initialization list to complete the initialization.

When a colleague is refactoring, he accidentally changes the final code to:

Class Final:public Intermediate2, public Intermediate3 {public:    Final (int A, int b, int c)        : Intermediate2 (A, B , c),          Intermediate3 (b, c)    {    }};
Class Intermediate1:public Base1, virtual public Base2 {public:    Intermediate1 (int A, int b, int c)        : Base1 (a), 
   base2 (b, c)    {    }};class intermediate2:public Intermediate1 {public:    Intermediate2 (int A, int b, int c) 
   : Intermediate1 (A, B, c),          Base2 (b, c)    {    }};class intermediate3:virtual public Base2 {public:    Intermediate3 (int b, int c)        : Base2 (b, c)    {    }};

It appears that the final constructor will call the constructors of Intermediate2 and Intermediate3 to initialize M_a, M_b, and M_c, respectively, to the specified value. However, the runtime discovers that the value of M_b and M_c is 0! Obviously, this is the default constructor that calls the Base2.

It turns out that the rule of C + + is that if there is a base class for virtual inheritance on the inheritance chain, the bottommost subclass is responsible for completing the construction of the partial members of the virtual base class. we can explicitly call the virtual base class constructor to complete the initialization. If you do not explicitly call the virtual base class's constructor, the compiler calls the virtual base class's default constructor. If the constructor of the virtual base class is not explicitly called, and the virtual base class does not have a default constructor defined, a compilation error occurs.

Many times, for intermediate classes on an inheritance chain, we also explicitly invoke the constructor of the virtual base class in its constructor, because once someone wants to create objects of those intermediate classes, we also want to ensure that they are properly initialized.

So, if we're going to initialize M_b and M_c to the specified value, the final constructor should be the correct way to do this:

    Final (int A, int b, int c)        : Base2 (b, c),          Intermediate2 (A, B, c),          Intermediate3 (b, c)    {    }

The complete test program is shown below, and interested students can compile and run them on their own. You can also step through the final constructor in the debugger to see which of the two Base2 's constructors were called.

#include "stdafx.h" #include <iostream>using namespace Std;class Base1 {public:base1 (int a): M_a (a) {}protected: int m_a;};    Class Base2 {public:base2 (int b, int c): M_b (b), M_c (c) {} Base2 (): M_b (0), M_c (0) {}protected:int m_b; int m_c;};            Class Intermediate1:public Base1, virtual public Base2 {public:intermediate1 (int a, int b, int c): Base1 (a), Base2 (b, c) {}};class intermediate2:public Intermediate1 {public:intermediate2 (int a, int b, int c    ): Intermediate1 (A, B, c), Base2 (b, c) {}};class intermediate3:virtual public Base2 {public: Intermediate3 (int b, int c): Base2 (b, c) {}};class final:public Intermediate2, public Intermediate3 {Publ    ic:final (int A, int b, int c): Base2 (b, C), Intermediate2 (A, B, c), Intermediate3 (b, c)    {} void Print () {cout<<m_a<< "," <<m_b<< "," <<m_c<<endl; }};int _tmain (inT argc, _tchar* argv[]) {Final finalobj (1, 2, 3); Finalobj.print (); return 0;}

Correct syntax for virtual inheritance class constructors in C + +

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.