Base class 成员初始化
Base class members initalization
为什么下面的代码不允许我初始化基 class 成员:
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
};
因为 base-class 被视为初始化列表中的成员。
您可以像这样描绘 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) {}
这段代码
class A {
public:
int x;
};
class B : public A {
public:
B() : x(0) {} // error
};
不正确,因为根据 C++ 标准(12.6.2 初始化基类和成员)
2 在 mem-initializer-id 中,在构造函数的 class 范围内查找初始非限定标识符,如果在该范围内未找到,则在包含构造函数的范围内查找定义。 [ 注意:如果构造函数的 class 包含与 class 的直接或虚拟基 class 同名的成员,则命名该成员或基的 mem-initializer-id class 并由单个标识符组成,指的是 class 成员。可以使用限定名称指定隐藏基 class 的 mem-initializer-id。 — 尾注 ] 除非 mem-initializer-id 命名构造函数的 class,构造函数 class 的非静态数据成员,或者该构造函数的直接或虚拟基础 class,内存初始化器格式错误。
你可以这样写
class A {
public:
int x;
};
class B : public A {
public:
B() : A{ 0 } {}
};
在 mem-initializer-list 中使用了直接基础 class 标识符。
注意这里用的是大括号A{ 0 }
而不是圆括号,因为class A
是一个聚合
在此代码段中
class A {
public:
int x;
};
class B : public A {
public:
B() { x = 0; } // ok
};
数据成员x
不在mem-initializer-list中,在默认初始化后在构造函数的主体中分配。那就是在构造函数的主体中使用了已创建对象的赋值运算符。
为什么下面的代码不允许我初始化基 class 成员:
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
};
因为 base-class 被视为初始化列表中的成员。
您可以像这样描绘 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) {}
这段代码
class A {
public:
int x;
};
class B : public A {
public:
B() : x(0) {} // error
};
不正确,因为根据 C++ 标准(12.6.2 初始化基类和成员)
2 在 mem-initializer-id 中,在构造函数的 class 范围内查找初始非限定标识符,如果在该范围内未找到,则在包含构造函数的范围内查找定义。 [ 注意:如果构造函数的 class 包含与 class 的直接或虚拟基 class 同名的成员,则命名该成员或基的 mem-initializer-id class 并由单个标识符组成,指的是 class 成员。可以使用限定名称指定隐藏基 class 的 mem-initializer-id。 — 尾注 ] 除非 mem-initializer-id 命名构造函数的 class,构造函数 class 的非静态数据成员,或者该构造函数的直接或虚拟基础 class,内存初始化器格式错误。
你可以这样写
class A {
public:
int x;
};
class B : public A {
public:
B() : A{ 0 } {}
};
在 mem-initializer-list 中使用了直接基础 class 标识符。
注意这里用的是大括号A{ 0 }
而不是圆括号,因为class A
是一个聚合
在此代码段中
class A {
public:
int x;
};
class B : public A {
public:
B() { x = 0; } // ok
};
数据成员x
不在mem-initializer-list中,在默认初始化后在构造函数的主体中分配。那就是在构造函数的主体中使用了已创建对象的赋值运算符。