班级成员初始化的顺序是什么?
我刚才读的this answer,如果你有下面的代码班级成员初始化的顺序是什么?
class Base
{
public Base()
{
}
}
class One : Base
{
string test = "text";
}
class Two : Base
{
string test;
public Two()
{
test = "text";
}
}
一个类initializaton One.test将基地前initalized ::基地之称。但是,在调用Base :: Base之后,Two.test将被初始化。
我想这是因为在这两种情况下,它是
- 领域< - 这包括One.test
- 基地:: Base的()
- 一::一()或二::两个()< - 初始化Two.test
我想我记得初始化列表只是在构造函数之前。 所以是初始化命令即可:
- 领域
- 基地初始化列表
- 基构造
- 自己的初始化列表
- 自己的构造
哪里做基础领域进来?当分配内存时或者在当前基类的初始化列表之前,是否所有字段都是初始化的?
在列表中您还可以想到其他步骤吗?
如果有人能给出一个好的概述,我将不胜感激。
C++初始化发生顺序如下:
- 基类,由左到右
- 成员变量,在他们宣布
的初始化顺序来自步骤1的基类递归地执行相同的步骤。因此,在任何成员变量初始化发生之前,构造函数的主体开始执行之前,所有基类都是完全构建的。
因此,当编译器遇到:
Two two;
首先,Two::Two
开始执行时,开始与该初始化列表。即使你没有写入一个基本类或者遗漏了一个基类的初始化,所有的碱基都通过初始化列表初始化。因此,实际运行的代码看起来更像是这样的:之前执行
Two::Two
:
One(),
test()
{
test = "text";
}
初始化列表构造的主体。因此,One
在Two::Two
正文开始执行之前完全构建。
反过来,One
看起来是这样的:
One::One()
:
Base()
{
string test = "test";
}
而且Base
是空的:
Base::Base()
{
}
那么,什么时候执行Two two;
发生的情况是:
-
Base
构造。 -
One
构造 - 自动可变
test
构造,初始化,并在One::One
-
Two::test
上下文破坏是缺省初始化 -
Two::test
的值指定为 “文本”
请注意,如果它认为这样做是安全的,那么其中的一部分,尤其是步骤4可能会被编译器优化。
@LokiAstari:哦,哎呀。我认为它看起来是这样的:'二类:公共一'和'一类:公共基地' –
'一'的情况是不完全一样的答案中描述。没有局部变量'test',而是具有初始值的成员变量。编译器将其转换为:'One():Base(),test(“test”){}' –
对于第一类初始化One.test将在Base :: Base被调用之前初始化。但是,在调用Base :: Base之后,Two.test将被初始化。
编号基地初始化之前任何成员。
在没有虚拟基础的简化(并且最常见)的情况下,对象初始化的顺序是:基于它们出现在类声明中的顺序,然后成员按它们出现的顺序在声明中(不是初始化列表)。只有在完成之后,才会输入构造函数的主体。
虚拟基础之前被初始化任何其他基地,在其他由深度优先搜索从第一个去到最后声明的基本判断。
在Two
的情况下,还有一个细节,可能重要的,我不知道你都知道,成员test
是在Two
初始化列表初始化,前进入构造函数体,和然后它被分配。
初始化一个基础包括递归基础,初始化列表,成员和构造函数,对吗? – Sarien
@Sarien:正确,完整的初始化,包括基础,成员和构造函数体。 –
其他人回答了这个问题。
但下面的Demo可能会有用。
#include <iostream>
class String
{
public:
String(char const* d) {std::cout << "String Constructor: " << d << "\n";}
String() {std::cout << "String Constructor: Default\n";}
String(String const& rhs) {std::cout << "String Constructor: Copy\n";}
String& operator=(String const& rhs){std::cout << "String Assignment\n";}
~String() {std::cout << "String Destructor\n";}
};
class Base
{
public: Base()
{
std::cout << "Base::Base()\n";
}
};
class One : Base
{
String test = "text";
};
class Two : Base
{
String test;
public: Two()
{
std::cout << "Two::Two\n";
test = "text";
}
};
int main()
{
std::cout << "Trying One\n";
One one;
std::cout << "==========\n\n\n";
std::cout << "Trying Two\n";
Two two;
std::cout << "==========\n\n\n";
std::cout << "Trying Base\n";
Base b;
}
这样做的结果是:
> ./a.out
Trying One // Outside the class about to start
Base::Base() // One: Calls the base constructor first Base
String Constructor: text // One: Constructs its members.
==========
Trying Two // Outside the class about to start
Base::Base() // Two: Calls the base construtor first
String Constructor: Default // Two: Constructs its members next
Two::Two // Two: Now entering the body of the constructor
String Constructor: text // Builds a string
String Assignment // Calls the assignment constructor.
String Destructor // Temporary destroyed.
========== //
Trying Base
Base::Base()
String Destructor // Destroys the string in Two
String Destructor // Destroys the string in One
那么你是如何连接使用C++一个C#的答案吗? – 0x499602D2
完全错过了。那么,我仍然想知道它在C++中的工作原理。 – Sarien
已编写的代码在C++中无效。 – deepmax