简体   繁体   中英

Order of member variables initialization of the base class in the derived class (constructor)

Did I correctly understand how the initialization is working in here? I will illustrate the steps:

  1. Base class constructor is called. We output 0 and increment m_i = 1 ;
  2. since m_x is before m_a in the member variables of the base class and we are u pre incrementing m_i . We output 2 and we increment m_i .
  3. we are creating an dynamic array of objects of type A. for m_a[0] we output 0 and we increment m_i ; for m_a[1] we output 0 and we increment m_i . m_i for m_a[0] is equal to 1 and m_i for m_a[1] is equal to 1 .
  4. finally we move to body of the constructor of the derived class and we output m_i = 2.

the output is : 02002

i didn't really understand why the output of m_i is equal 2 when we get into the body of the base constructor? Shouldn't m_i be equal to 3 after step 2?


source code

   #include <iostream>

class A
{
public:
    A(int n = 0)
        : m_i(n)
    {
        std::cout << m_i;
        ++m_i;
    }

protected:
     int m_i;
};

class B
    : public A
{
public:
    B(int n = 5) : m_a(new A[2]), m_x(++m_i){ std::cout << m_i; }

    ~B() { delete [] m_a;}

private:
    A m_x;
    A *m_a;

};

int main()
{
    B b;
    std::cout << std::endl;

    return 0;
}

Before I explain the problem, let me say this: if your object's initialization is so complex that it requires the detailed knowledge I'm about to relate, then fix that . Overcomplicating your initialization is to nobody's benefit.

Now, let's look at what happens when you construct an object of type B by calling its default constructor.

Since B::A is not mentioned in the member initializer list, it will be default initialized. That will call A(int) with its default value of 0. The result of this will be initializing B::A::m_i with the value 0, followed by outputing that value, followed by incrementing B::A::m_i to the value 1.

Now, we initialize the members of B . The first member to be initialized is B::m_x . The member initializer for this reads and increments the value of B::A::m_i , which is a validly initialized value that happens to be 1 before this operation. So before calling A(int) for B::m_x , B::A::m_i takes the value 2.

B::m_x is initialized via a call to A(int) with the value 2. It stores that value in B::m_x.m_i , outputs it, and increments it by one.

Next, we initialize B::m_a . The member initializer initializes it via a call to new A[2] , which will default construct 2 instances of A . These are all completely irrelevant to your question, as they are in no way related to B::A::m_i . But it does output two zeros.

After initializing B::m_a , we enter B 's default constructor itself.There, it simply outputs the value of B::A::m_i . Which if you recall, was last set to 2. So that's what it outputs.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM