在类初始化常量成员时
In class initialization of constant member
为什么编译器(clang)抱怨mymy
未初始化,当我明确地告诉它是一个常量值,保持50。为什么它允许我把它改成23…当我告诉他要保持稳定的时候?
#include <iostream>
class Base
{
public:
Base(int y) : my(y) {std::cout << "Base:" << my << std::endl;}
private:
int my;
};
class Derived : public Base
{
public:
Derived() : Base(mymy), mymy(23) {std::cout << "Derived:" << mymy << std::endl;}
private:
const int mymy = 50;
};
int main()
{
Derived a;
}
奇怪的是,coliru编译时没有标记。http://coliru.stacked-crooked.com/a/63629c2d99bf6f43(是的,我知道将其更改为static
将解决此问题)
标准规定(§12.6.2/101,重点是我的):
如果给定的非静态数据成员既具有默认成员初始化式又具有mem初始化式,则执行由mem初始化式指定的,忽略非静态数据成员的默认成员初始化式。[示例:给定
struct A { int i = /* some integer expression with side effects */ ; A(int arg) : i(arg) { } // ... };
A(int)
构造函数将简单地将i
初始化为arg
的值,并且i
的默认成员初始化器中的副作用不会发生。端例子)
http://coliru.stacked-crooked.com/使用g++,不产生警告,但结果是一样的:Base
不是用50
或23
初始化的,而是用0
初始化的。您可以通过在mymy
:
class Derived: public Base {
public:
Derived() : Base(mymy), mymymy(mymy), mymy(23) {
std::cout << "Derived:" << mymy << std::endl;
std::cout << "Derived:" << mymymy << std::endl;
}
int mymymy;
const int mymy = 50;
};
coliru输出:
Base:4197208
Derived:23
Derived:4197208
Main:23
但是如果你在mymy
之后添加一个属性:
class Derived : public Base {
public:
Derived() : Base(mymy), mymy(23) {
std::cout << "Derived:" << mymy << std::endl;
std::cout << "Derived:" << mymymy << std::endl;
}
const int mymy = 50;
int mymymy= mymy;
};
在构造函数的成员初始化列表中提供的值将被使用:
Base:0
Derived:23
Derived:23
Main:23
关于const
限定:您总是可以在构造函数的member-list-initializer中初始化const
成员(这是唯一可以将它们与默认成员初始化器一起初始化的地方)。
我不知道标准中是否有更明确的引用,但是§12.6.2/71(这个例子很明确):
mem-initializer中的expression-list或带括号的init-list用于根据8.5的直接初始化规则初始化指定的子对象(或者,在委托构造函数的情况下,初始化完整的类对象)。(例子:struct B1 { B1(int); /* ... */ }; struct B2 { B2(int); /* ... */ }; struct D : B1, B2 { D(int); B1 b; const int c; }; D::D(int a) : B2(a+1), B1(a+2), c(a+3), b(a+4) { /* ... */ } D d(10);
-end example]
1
<子><一口>一口>最新c++ 17标准草案(N4594)。子>
如果你使用了tor初始化器,那么在类初始化中会被忽略。
考虑调用实参为mymy
的基类构造函数
Derived() : Base(mymy), mymy(23) {std::cout << "Derived:" << mymy << std::endl;}
不正确,因为派生类的数据成员尚未初始化。
- 私有类型的静态常量成员
- constexpr构造函数需要常量成员函数时出现问题
- 是否可以同时声明一个类成员的常量/非常量?
- 当成员值从指针更改为非指针时,C++常量问题
- 常量公共成员有什么问题?
- Clang 格式 10.0 与 5.0 常量成员函数的格式不同
- C++/QT:使用指向私有成员的常量指针作为只读数据共享
- 空指针常量 (nullptr)、空指针值和空成员指针值之间有什么区别?
- 为什么"具有常量成员的结构"类型的指针不能指向"具有非常量成员的结构"?
- 初始化依赖于子类的继承类的常量类成员
- 常量成员函数中成员变量的类型
- 如何为非常量和常量重载实现一次成员函数?
- 如何处理运算符=中的常量成员?
- 移动类的成员作为常量引用参数传递
- 为什么我可以改变常量对象中的成员变量,这是返回常量对象函数的结果?
- 常量和引用成员函数限定符
- 返回对常量结构(指针类型)成员的引用:明显的左值到右值转换
- 常量成员和没有setter的私有成员之间有什么区别
- 如何初始化类C++的成员常量向量
- 当我希望调用基类构造函数时,如何在派生类中初始化成员常量引用