对象初始化的顺序

一个对象初始化时的顺序是:

在不考虑继承关系时,那么顺序如下:

static Field -->static ctor --> instance Field -->instance ctor

原因:因为static ctor可能会用到static Field,所以必须先字段

考虑继承关系时,则是

class Base{}

class Derived:Base{}

Derived static Field --> Derived static ctor --> Derived instance Field --> Base instance Field -->Base instance ctor --> Dervied instance ctor

试想有这么一个基类,它在构造函数中调用了一个虚方法。然后又有这么一个派生类,它重写了基类的那个虚方法,并且在这个虚方法中访问了它自己的一个实例成员字段。

这一切都是完全合法的(至少在C#的世界里是这样的),对吧?在实例化一个派生类对象的过程中,其基类的构造函数会被调用,接着那个虚方法也会被调用,再接着派生类的实例成员字段会被访问。

所以此时此刻,这个类的实例成员字段必须是已被准备好了的!因此,派生类的实例成员字段必须先于基类部分被构造。

总之就是为了防止virtual function可能调用派生类中的字段,所以必须要先实例化好了.

一个最容易忽略的初始化还有这么多名堂...

时间: 2024-10-08 06:49:57

对象初始化的顺序的相关文章

java对象初始化的顺序

Java代码 public class Son extends Father { String value = null;//2 public Son() { super();  //1 System.out.println("Son:  " + value);//3 } public static void main(final String[] args) { new Son(); } } class Father { public Father() { if (this inst

阿里巴巴面试题--Java对象初始化

转自 http://blog.csdn.net/ysjian_pingcx/article/details/19605335 Java对象初始化 这是一道阿里巴巴的关于Java对象初始化的面试题,堪称经典,代码很简单(编写格式做了些修改),但是需要面试者对Java中对象初始化有一个透彻的认识,那么通过这道面试题,对我有点启发,所以希望在这里分享给大家,希望能给迷惘的初学者一起指引,下面我们直入主题,先看看代码: 1 public class InitializeDemo { 2 private

Java 对象初始化顺序 执行顺序

先看一道Java面试题: 求这段程序的输出. 解答此题关键在于理解和掌握类的加载过程以及子类继承父类后,重写方法的调用问题: 从程序的执行顺序去解答: 1.编译:当这个类被编译通知后,会在相应的目录下生成两个.class 文件.一个是 Base.class,另外一个就是Base$Sub.class.这个时候类加载器将这两个.class  文件加载到内存 2.Base base= new Sub(): 声明父类变量base对子类的引用,JAVA类加载器将Base,Sub类加载到JVM(Java虚拟

Java对象初始化顺序(一)

---恢复内容开始--- 偶尔翻到了关于Java对象初始化顺序的面试题,重新复习了一下,顺便做笔记. 1.父类子类构造函数执行的先后顺序 public class Test2 { public int Field; //step 1 public Test2(){ Field = 1; } } /*************************************************/ /** * 次类的目的仅是为了验证父类子类构造函数执行的先后顺序 */ public class T

C#对象初始化的先后顺序

using System; namespace ConsoleApp { class Program { static void Main() { A a = new B(); Console.ReadKey(); } } class A { int z = 1;////////////////////////////////////////////7 int k; static int i = 1;/////////////////////////////////5 static int j;

Java变量、Java对象初始化顺序

局部变量与成员变量: 局部变量分为: 行参:在方法签名中定义的局部变量,随方法的结束而凋亡. 方法内的局部变量:必须在方法内对其显示初始化,从初始化后开始生效,随方法的结束而凋亡. 代码块内的局部变量:必须在代码块内对其显示初始化,从初始化后开始生效,随代码块的结束而凋亡. 成员变量: 静态属性:类加载时初始化,随着类的存在而存在: 非静态属性:随着实例的属性存在而存在: 关于他两的区别: 1.局部变量不可以加static: 2.局部变量不可以加public.protected.private:

类加载与对象初始化

1. 初始化原因:避免发生空指向异常. 2. 类加载与初始化的顺序: 2.1 类加载时间:          每个类的编译代码都存在于他自己的独立文件中,该文件的加载通常发生在创建类的第一个对象时,或是访问类的static域或static方法时. 2.2 初始化顺序:(先父类后子类,创建对象之前先对类中的域进行初始化)        首先,类加载器主动加载主类(主类的初始化顺序与下面普通类一样),找到main方法,在main方法中根据第一行要创建的对象,加载该类的字节码文件,如果编译器注意到她有

理解隐式类型、对象初始化程序和匿名类型

在C# 3.0中,几乎每个新特性都是为LINQ服务的.所以,本文将介绍下面几个在C# 3.0中引入的新特性: 自动实现的属性 隐式类型的局部变量 对象和集合初始化程序 隐式类型的数组 匿名类型 其实这几个特性都是比较容易理解的,对于这几个特性,编译器帮我们做了更多的事情(想想匿名方法和迭代器块),从而简化我们的代码. 自动实现的属性 在C# 3.0以前,当我们定义属性的时候,一般使用下面的代码 public class Book { private int _id; private string

C++静态初始化的顺序

这两天项目代码中遇到一个很疑惑的问题,问题可以描述为:一个静态成员初始化的时候直接core掉,该静态成员初始化时通过另外一个文件中静态成员来完成.该问题同样发生在全局对象上.该问题可以描述为今天要讨论的:变量的静态初始化顺序. 具体可以用代码简述如下: //test1.cpp #include <string> std::string a = "test"; //test2.cpp #include <iostream> extern std::string a