C++和C#对象初始化顺序

转自:http://fafeng.blogbus.com/logs/17747724.html

C++构造函数调用顺序

1. 如果类里面有成员类,成员类的构造函数优先被调用;

2. 创建派生类的对象,基类的构造函数优先被调用(也优先于派生类里的成员类);

3. 基类构造函数如果有多个基类,则构造函数的调用顺序是某类在类派生表中出现的顺序而不是它们在成员初始化表中的顺序;

4. 成员类对象构造函数如果有多个成员类对象,则构造函数的调用顺序是对象在类中被声明的顺序而不是它们出现在成员初始化表中的顺序;

5. 派生类构造函数,作为一般规则派生类构造函数应该不能直接向一个基类数据成员赋值而是把值传递给适当的基类构造函数,否则两个类的实现变成紧耦合的(tightly coupled)将更加难于正确地修改或扩展基类的实现。(基类设计者的责任是提供一组适当的基类构造函数)

#include <iostream>

#include <string>

class A{

public:A{…}

~A{…}

}

class B{

public:B{…}

~B{…}

}

class D{

public:D{…}

~D{…}

}

class E{

public:E{…}

~E{…}

}

class C :public A,public B{

public:C{…}

private:D objD_; E objE_;

~C{…}

}

int main(void){

C test;

return 0;

}

运行结果是

A{…}//派生表中的顺序

B{…}

D{…}//成员类的构造函数优先被调用

E{…}

C{…}

~C{…}

~E{…}

~D{…}

~B{…}

~A{…}

对于全局对象(global object),VC下是先定义先初始化,但C++标准没做规定。全局对象默认是静态的,全局静态(static)对象必须在main()函数前已经被构造,告知编译器将变量存储在程序的静态存储区,由C++ 编译器startup代码实现。startup代码是更早于程序进入点(main 或WinMain)执行起来的代码,它能做些像函数库初始化、进程信息设立、I/O stream产生等等动作,以及对static对象的初始化动作(也就是调用其构造函数);在main()函数结束后调用它的析构函数。

C#对象初始化

1. 先变量后构造函数。变量先被初始化,然后构造函数被执行

2. 先静态化后实例化。当一个类被访问时,静态变量和构造函数最先被初始化.接着是对象的实例化变量和构造函数被初始化

3. 先派生类后基类。对于变量和静态构造函数,派生对象在基对象之前被初始化.比如C类派生自B类,B类派生自A类,那么变量和静态构造函数被初始化次序是C-B-A.

4. 除了实例构造函数。对于实例构造函数,基类构造函数在派生类构造函数之前执行,实例构造函数被执行次序是A-B-C.

5. 不要假定变量的次序。Fields依据它们在源文件中的声明的顺序依次初始化.然而,自从程序员和工具可以随意安排变量的声明后,你不应该在依靠变量任何特别的次序初始化

6. 对虚方法用两个阶段的构建。避免从一个构造器调用虚方法. 如果在初始化一个对象时需要调用一些虚方法,应在完整构造该对象的地方使用两阶段的构建,并随后调用已构造对象的初始化方法。