C# 子类实例化过程
刚研究了一下C#子类实例化的过程。
首先我遇到了如下一个问题:
有类A,里面写了一个有参的构造函数,并没有提供默认的无参构造函数。现在类B继承了类A,没有写任何的构造函数。
这时如果想实例化类B就会产生错误了。首先,子类B中没有构造函数,编译器要为子类B生成默认的构造函数,但是首先得去调用其父类A默认的构造函数,而父类A中没有提供默认的无参构造函数,所以发生错误。一般是这么解决:
class A
{
public A(string name)
{
//some code
}
}
class B : A
{
public B(string name) : base(name)
{
//No need code
}
}
现在明确两个基本知识:
1. 有继承关系的几个类中,构造函数是由上至下调用的,即首先调用基类的构造函数。(父亲会的,儿子也会,不先把父亲弄出来,儿子何来会?)
2. 有继承关系的几个类中,如果是调用默认的无参构造函数,就要注意我上面提到的问题。
--------------
接下来说明类实例化时的具体过程(参考网络资料):
1)先不考虑继承关系,执行顺序为:
- 静态字段
- 静态构造方法
- 实例字段
- 实例构造方法
属性和方法是在调用的时候才执行,这里就不考虑了。如何理解上面的执行过程?假如让我来设计执行过程,我该如何考虑,依据是什么?
首先,静态的东西是大家共享的,也就是相同的。应该先关心共享的东西,再关心个人的东西,即“先公后私”。其次,实例化之前,应该先初始化自己的内部字段。
2)考虑继承关系,执行顺序为:
- 子类的静态字段
- 子类的静态构造方法
- 子类的实例字段
- 父类的静态字段
- 父类的静态构造方法
- 父类的实例字段
- 父类的实例构造方法
- 子类的实例构造方法
在子类的实例字段和子类的实例构造方法之间,加入了父类的执行顺序。即我上面说的基本知识点1。
这里需要特别注意的是,并不是每次实例化都是上面的顺序。因为静态的成员只是在第一次实 例化的时候执行,以后再实例化都不会在执行。很好理解,静态的成员意味着大家共享,且只有这一个。第一次实例化得到静态成员后,以后大家都共享,再次实例 化,没有必要也不允许执行静态成员的部分。
------
补充说明(参考网络资料):
1、构造引用类型的对象时,调用实例构造方法之前,为对象分配的内存总是先被归零,构造器没有显式重写字段,字段的值为0或者null
2、原则上讲,类中的字段应该在实例构造方法内初始化。C#编译器提供了简化的语 法,允许在变量定义的时候初始化。但在幕后,C#会把这部分代码搬到构造方法内部。因此,这里存在代码膨胀的问题。多个字段在定义时初始化,同时存在多个 构造方法,每个构造方法都会把这些字段初始化的代码搬到自己的内部,这样造成代码的膨胀。为了避免这样情况,可以把这些字段的初始化放到一个无参构造方法 内,其他的构造方法显式调用无参构造方法。
3、初始化类的字段有两种方法,①使用简化语法,在定义的时候初始化;② 在构造方法内初始化。使用简化语法初始化的代码,会被搬到构造方法内。特别注意,在生成的IL中,父类构造方法会夹在 ①和②之间。因此,实例化子类的时候,会先执行①,再执行父类构造方法,然后执行②。现在问题来了,假如在父类构造方法内,调用虚方法,虚方法回调子类的 方法,子类方法使用字段,这时候字段的值是简化语法初始化的值。
C# 子类实例化过程的更多相关文章
- java中子类实例化过程中的内存分配
知识点: 子类继承父类之后,实例化子类时,内存中子类是如何分配内存的呢? 下面,自己会结合一个例子,解释一下,一个子类实例化过程中,内存是如何分配的 参考博客:http://www.cnblogs.c ...
- java继承子类实例化过程(细节解释)
1 package face_08; 2 class Fu{ 3 Fu(){ 4 super(); 5 show(); 6 return; 7 } 8 void show() { 9 System.o ...
- 【Java】子类实例化过程
子类对象实例化的全过程 子类继承父类以后,就获取了父类中声明的属性或方法.创建子类的对象,在堆空间中,就会加载所有父类中声明的属性. 当我们通过子类的构造器创建子类对象时,我们一定会调用其父类的构造器 ...
- Java 子类实例化对象的过程
子类实例化是否会实例化父类? 不会.父类在子类实例化过程中是并没有被实例化,java中new子类没有实例化父类,只是调用父类的构造方法初始化了,子类从父类继承来的属性,这个调用是子类的对象调用的父类的 ...
- Java继承--子类的实例化过程
一个对象的实例化过程: Person p = new Person(); 1,JVM会读取指定的路径下的Person.class文件,并加载进内存,并会先加载Person的父类(如果有直接的父类的情况 ...
- java继承子父类构造函数-子类的实例化过程
1 /* 2 * 子父类中的构造函数的特点. 3 * 在子类构造对象时,发现,访问子类构造函数时,父类也运行了. 4 * 为什么呢? 5 * 原因是:在子类的构造函数中第一行有一个默认的隐式语句.su ...
- Java子父类中的构造函数实例化过程
其实我们发现子类继承父类操作很简单,如果要是去深入的研究下会发现,实例化过程并非是我们看到的那样,我们就以代码举例来说明: 问大家,以下代码执行会输出什么呢? package com.oop; /** ...
- java对象的实例化过程
简单类对象的实例化过程 1.在方法区加载类: 2.在栈内存申请空间,声明变量P: 3.在堆内存中开辟空间,分配对象地址: 4.在对象空间中,对对象的属性进行默认初始化,类成员变量显示初始化: 5.构造 ...
- 基础篇:详解JAVA对象实例化过程
目录 1 对象的实例化过程 2 类的加载过程 3 触发类加载的条件 4 对象的实例化过程 5 类加载器和双亲委派规则,如何打破双亲委派规则 欢迎指正文中错误 关注公众号,一起交流 参考文章 1 对象的 ...
随机推荐
- openresty总结
协程 1.例如当获取的数据没有前后依赖关系时,可以使用ngx.thread.spawn和ngx.thread.wait同时从数据库不同的库.表或者不同来源(mysql,redis等)获取数据. htt ...
- Exercise01_03
public class TuAn{ public static void main(String[] args){ System.out.println(" J A V V A" ...
- 13test02:阶乘
//假设32位int型变量y是表示最大人数的x的阶乘,即y=x!,当x最大值取什么时,y取最大值 //,且乘法不溢出. #include<iostream> using namespace ...
- css sprite demo
一张图片,用CSS分割成多个小图标. css样式: .icon{ background:url(../images/tabicons.png) no-repeat;width:18px; line-h ...
- Python自带的hmac模块
Python自带的hmac模块实现了标准的Hmac算法 我们首先需要准备待计算的原始消息message,随机key,哈希算法,这里采用MD5,使用hmac的代码如下: import hmac mess ...
- Word2010插入页码分节符
不是分页符,分节符主要是为了插入前后两种不同类型的页码,比如前面查罗马数字,从目录开始插入阿拉伯数字.
- win10 彻底删除mysql步骤
转载自:https://blog.csdn.net/sxingming/article/details/52601250 1. 停止MySQL服务 开始->所有应用->Windows管理工 ...
- Discuz! 6.x/7.x 全局变量防御绕过漏洞
受影响产品: Discuz! 6.x/7.x 漏洞描述: 由于php5.3.x版本里php.ini的设置里request_order默认值为GP,导致Discuz! 6.x/7.x 全局变量防御绕过漏 ...
- mahout运行测试与数据挖掘算法之聚类分析(一)kmeans算法解析
在使用mahout之前要安装并启动hadoop集群 将mahout的包上传至linux中并解压即可 mahout下载地址: 点击打开链接 mahout中的算法大致可以分为三大类: 聚类,协同过滤和分类 ...
- Linux下 安装VMware Tools工具
Linux下需要安装VMware Tools工具 Linux下需要安装VMware Tools工具来实现主机和虚拟机直接文件复制粘贴功能,安装方法如下: ①点击虚拟机VM菜单栏--虚拟机--安装VMw ...