开发者

Should I call the base class default constructor in the initialization list?

开发者 https://www.devze.com 2023-02-28 19:34 出处:网络
class A : public B { ... } // case I : explicitly call the base class default constructor A::A() : B() { ...
class A : public B
{
  ...
}

// case I : explicitly call the base class default constructor
A::A() : B()
{
  ...
}

// case II : don't call the bas开发者_如何学运维e class default constructor
A::A() // : B()
{
  ...
}

Is the case II equal to case I?

To me, I assume that the default constructor of base class B is NOT called in case II. However, despite still holding this assumption, I have run a test which proves otherwise:

class B
{
public:
    B()
    {
        cout << "B constructor" << endl;
    }
};

class A : public B
{
public:
    A()
    {
        cout << "A constructor" << endl;
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    A a;
    return 0;
}

// output from VS2008

B constructor
A constructor
Press any key to continue . . .


The base class constructor is called in both cases.

Here is a link to an article with more info.


If B doesn't have a user declared constructor, the behavior is different. Compare:

struct SimpleAggregate {
  int a;
  float b;
};

struct ClassWrapper : SimpleAggregate {
  ClassWrapper() : SimpleAggregate() { }
};

ClassWrapper w;

Now, w.a and w.b are guaranteed to be zero. If you would have left off the explicit initialization of the base class, they would have indeterminate values.


It may be unknown to you that, despite the syntax, the above use of SimpleAggregate() does not call the default constructor, though. It simply value initializes the base class (we have several good answers here on Stackoverflow about what "value initialization" is), not calling the default constructor because there is none user declared.


If the base class constructor doesn't take any argument, then explicit mention of it in the initialization list is not needed.


To complete the learning experience and develop deeper understanding, you could start to modify things slightly. For instance, what happens when B has no default constructor? Does it even compile? Other slight modifications like this will provide a great learning experience.

That said, in my experience it's generally better to do this

A::A() : B() { ... } 

than

A::A() { ... } 

because the former is more explicit, and it will get you to think about what's really going on with base class initialization. You will probably avoid hidden behavior by spelling out things explicitly.


Every class that is derived from some other class must call the base class' constructor. A derived class can only be constructed once all base class' are fully constructed. So it doesn't matter if you call the base class' constructor or not. If you don't call, as long as there is a default constructor available for compiler to determine, it will be called. Otherwise compiler will throw error.

0

精彩评论

暂无评论...
验证码 换一张
取 消