使用初始化列表时未调用两次基构造函数

Base constructor not called twice when using initialization list

本文关键字:两次 构造函数 调用 初始化 列表      更新时间:2023-10-16
#include <iostream>
using namespace std;
class Counter
{
protected:
    unsigned int count;
public:
    Counter() : count(0) {cout << "nCounter Default Constructor";}
    Counter(int i ) : count (i) {cout << "nCounter Argument Constructor";}
    unsigned int getData ()
    {
        return count;
    }

    Counter operator ++ () // increment (prefix)
    {
        ++count;
        return Counter(count);
    }
};
class inCounter : public Counter
{
public:
    inCounter() : Counter() { cout << "ninCounter Default Constructor"; }
    inCounter(int c ) : Counter ( c ) {cout << "ninCounter Argument Constructor";}
    Counter operator -- ()
    {
        --count;
        return Counter ( count ) ;
    }
};
void main ()
{
    inCounter c1(10); }

我原以为输出是:

计数器参数构造函数

inCounter参数构造函数

计数器参数构造函数

但结果是

计数器参数构造函数

inCounter参数构造函数

为什么会这样?

我期望第一个输出的原因是,在创建对象c1的过程中,首先调用基类构造函数,因此打印"Counter Argument Constructor"。然后,调用派生类构造函数,因此打印"inCounter Argument Constructor"。但是派生类构造函数再次调用Counter构造函数。因此,应再次打印"Counter Argument Constructor"

如果通过初始化列表初始化成员,则将替换编译器将执行的默认初始化

这不是一个"附加"调用,因为这意味着一个对象被构造了两次。

此外,您可以通过在您的案例中使用默认参数来简化事情。这将允许您删除一些不必要的构造函数。

inCounter(int c=0) : Counter (c) 
{
  cout << "ninCounter Argument Constructor";
}

我想您对程序中的以下行感到困惑

inCounter(int c ) : Counter ( c ) {cout << "ninCounter Argument Constructor";}

即使您的代码中有Counter(c(,它也不会调用构造函数两次。相反,它调用基类构造函数的参数化版本,如下所示。

Counter(int i ) : count (i) {cout << "nCounter Argument Constructor";}

所以正确的输出是

Counter Argument Constructor
inCounter Argument Constructor