【问题标题】:Base class members initalization基类成员初始化
【发布时间】:2020-03-28 12:17:31
【问题描述】:

为什么下面的代码不允许我初始化基类成员:

class A { 
public:
   int x;
};

class B : public A {
public:
    B() : x(0) {} // error
};

虽然以下是:

class A { 
public:
   int x;
};

class B : public A {
public:
    B() { x = 0; } // ok
};

【问题讨论】:

  • “为什么”很难明确回答。但是现代 C++ 问题的解决方案是在 A 类定义中写 public: int x = 0;
  • 成员初始值设定项列表仅适用于类的直接成员,而不适用于继承的成员。您应该考虑创建A 的默认构造函数,在其中初始化A 的成员,或者如@hyde 所述,对变量进行内联初始化。

标签: c++ class inheritance constructor initialization


【解决方案1】:

因为基类被视为初始化列表中的成员。

您可以像这样描绘B 类型的对象:

class C {
public:
    A parent;
};

在此示例中,您将无法初始化 parent.x,而只能初始化 parent。 即使您可以访问和修改正文中的parent.x,就像您所做的那样,您也无法访问其在初始化列表中的成员:

C::C() {
    parent.x = 5; // Works
}

C::C() : parent.x(5) {} // Won't work

另一方面,如果你有 A 的构造函数,就像

A::A(int i): x(i) {}

,您可以在 C 的初始化列表中使用此构造函数:

C::C(): parent(5) {} // Works and does what you want

如果你有 A 的构造函数,你对 B 有同样的选择:

B::B(): A(5) {}

【讨论】:

    【解决方案2】:

    这段代码sn-p

    class A { 
    public:
       int x;
    };
    
    class B : public A {
    public:
        B() : x(0) {} // error
    };
    

    不正确,因为根据 C++ 标准(12.6.2 初始化基和成员)

    2 在 mem-initializer-id 中,在构造函数类的范围内查找初始的非限定标识符,如果在该范围内找不到,则在包含构造函数定义的范围内查找。 [注:如果构造函数的类包含与该类的直接或虚拟基类同名的成员,则命名该成员或基类并由单个标识符组成的mem-initializer-id指的是类成员。可以使用限定名称指定隐藏基类的 mem-initializer-id。 — end note ] 除非 mem-initializer-id 命名构造函数的类,构造函数类的非静态数据成员,或该类的直接或虚拟基类,否则 mem-initializer 是非良构的。

    你可以写

    class A { 
    public:
       int x;
    };
    
    class B : public A {
    public:
        B() : A{ 0 } {}
    };
    

    在 mem-initializer-list 中使用直接基类标识符的位置。

    注意这里使用了大括号A{ 0 } 而不是括号,因为class A 是一个聚合。

    在这段代码中sn-p

    class A { 
    public:
       int x;
    };
    
    class B : public A {
    public:
        B() { x = 0; } // ok
    };
    

    数据成员x 不存在于mem-initializer-list 中,并在默认初始化后在构造函数的主体中分配。也就是说,在构造函数的主体中,对已创建的对象使用了赋值运算符。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-04-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-10
      • 1970-01-01
      • 2010-11-10
      相关资源
      最近更新 更多