在C++中,当初始化一个子类对象时,初始化顺序为: 首先是基类,然后是成员变量按照它们在类中声明的顺序进行初始化。初始化列表中的顺序不影响实际的初始化顺序。
示例代码
#include <iostream>
class Base
{
public:
Base(int val) : b(val)
{
std::cout << "Base initialized with value: " << b << std::endl;
}
private:
int b;
};
class Derived : public Base
{
public:
Derived(int x, int y) : Base(y), a(x), c(a + y), b(0)
{
std::cout << "Derived constructor: a = " << a << ", c = " << c << ", b = " << b << std::endl;
}
private:
int a;
int c;
int b;
};
int main()
{
Derived obj(5, 10);
return 0;
}
代码解释
-
类声明与成员变量顺序:
Base
类有一个私有成员变量b
。Derived
类继承自Base
类,并且有三个私有成员变量:a
、c
和b
。
-
构造函数初始化列表:
Derived
类的构造函数包含一个初始化列表:Base(y), a(x), c(a + y), b(0)
。- 尽管初始化列表按这个顺序书写,成员变量的实际初始化顺序仍按它们在类中声明的顺序进行。
-
成员变量初始化顺序:
Base
类的构造函数首先被调用,以y
的值初始化基类的成员变量b
。- 然后
Derived
类的成员变量按声明顺序依次初始化:a
、c
和b
。
-
运行结果:
- 创建
Derived
对象obj
时:- 基类
Base
的构造函数被调用,输出 “Base initialized with value: 10”。 - 然后
Derived
类的成员变量按声明顺序初始化:a
被初始化为5
。c
被初始化为a + y
,此时a
已经被初始化为5
,y
为10
,所以c
被初始化为15
。- 最后
b
被初始化为0
。
- 基类
- 创建
代码运行结果
Base initialized with value: 10
Derived constructor: a = 5, c = 15, b = 0
关键点总结
- 基类优先:基类部分总是在派生类部分之前初始化。
- 声明顺序:派生类的成员变量按照它们在类定义中的声明顺序进行初始化,而不是构造函数初始化列表中的顺序。
- 初始化列表中的顺序:初始化列表的顺序可以与声明顺序不同,但实际的初始化顺序还是按照声明顺序。
- 初始化中的依赖关系:在初始化列表中使用已初始化的变量(如
c(a + y)
)是安全的,但要确保所有变量在它们被使用前已被初始化。