避免在构造函数中调用虚方法(Do not call overridable methods in constructors)
CLR中说道,不要在构造函数中调用虚方法,原因是假如被实例化的类型重写了虚方法,就会执行派生类型对虚方法的实现。但在这个时候,尚未完成对继承层次结构中所有字段的初始化。所以,调用虚方法会导致不可预测的行为。归根结底,这是由于调虚方法时,直到运行时之前,都不会选择执行该方法的实际类型。
在MSDN中,也给我我们详细的提示和范例。
https://msdn.microsoft.com/en-us/library/ms182331.aspx
那我们就亲手来测试一下,新建两个类,Perople类,Chinese类,先不要看结果,看到下面这两个类,想想在实例化Chinese的时候,会是什么输出结果呢?
public class People
{
public People()
{
PeopleSayHello();
} public virtual void PeopleSayHello()
{
Console.WriteLine("hello");
}
}
public class Chinese : People
{
private bool HaveAbility { get; set; } public Chinese()
{
HaveAbility = true;
} public override void PeopleSayHello()
{ Console.WriteLine((HaveAbility?"有":"没有")+"能力说你好");
}
}
接下来来看调用和输出结果吧:


是不是和你在脑海里运行的结果相同?
其实原因在第一句话中已经说的比较清晰了,更通俗的说就是在派生类实例化的时候,如果没有显式调用基的任意一个构造函数,那么默认选择基类的无参构造。所以在本例中,实例化Chinese的时候,首先执行了基类的无参构造。
和实例构造器初始化的顺序也相关,在创建实例的时候,首先为数据字段分配内存,然后初始化对象附加字段,包括类型对象的指针引用,最后才调用类型的构造函数设置对象的初始状态。
避免在构造函数中调用虚方法(Do not call overridable methods in constructors)的更多相关文章
- C# 构造函数中调用虚方法的问题
请看下面代码: using System; public class A{ public A(){ M1(); } public virtual void M1(){} } public class ...
- [C#解惑] #1 在构造函数内调用虚方法
谜题 在C#中,用virtual关键字修饰的方法(属性.事件)称为虚方法(属性.事件),表示该方法可以由派生类重写(override).虚方法是.NET中的重要概念,可以说在某种程度上,虚方法使得多态 ...
- 关于在C#中构造函数中调用虚函数的问题
在C#中如果存在类的继承关系,应避免在构造函数中调用虚函数.这是由于C#的运行机制造成的,原因如下: 新建一个类实例时,C#会先初始化该类(对类变量赋值,并将函数记在函数表中),然后再初始化父类.构造 ...
- C++ 构造函数中调用虚函数
我们知道:C++中的多态使得可以根据对象的真实类型(动态类型)调用不同的虚函数.这种调用都是对象已经构建完成的情况.那如果在构造函数中调用虚函数,会怎么样呢? 有这么一段代码: class A { p ...
- 【校招面试 之 C/C++】第10题 C++不在构造函数和析构函数中调用虚函数
1.不要在构造函数中调用虚函数的原因 在概念上,构造函数的工作是为对象进行初始化.在构造函数完成之前,被构造的对象被认为“未完全生成”.当创建某个派生类的对象时,如果在它的基类的构造函数中调用虚函数, ...
- C++中构造函数能调用虚函数吗?(答案是语法可以,输出错误),但Java里居然可以
环境:XPSP3 VS2005 今天黑总给应聘者出了一个在C++的构造函数中调用虚函数的问题,具体的题目要比标题复杂,大体情况可以看如下的代码: class Base { public: Base() ...
- EC笔记,第二部分:9.不在构造、析构函数中调用虚函数
9.不在构造.析构函数中调用虚函数 1.在构造函数和析构函数中调用虚函数会产生什么结果呢? #; } 上述程序会产生什么样的输出呢? 你一定会以为会输出: cls2 make cls2 delete ...
- 编写高质量代码改善C#程序的157个建议——建议95:避免在构造方法中调用虚成员
建议95:避免在构造方法中调用虚成员 在构造方法中调用虚方法会带来一些意想不到的错误,虽然这种方法不常见,但还是需要注意这类陷阱. static void Main() { American amer ...
- 读书笔记 effective c++ Item 9 绝不要在构造函数或者析构函数中调用虚函数
关于构造函数的一个违反直觉的行为 我会以重复标题开始:你不应该在构造或者析构的过程中调用虚函数,因为这些调用的结果会和你想的不一样.如果你同时是一个java或者c#程序员,那么请着重注意这个条款,因为 ...
随机推荐
- Android摘抄总结
著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处.作者:葛小葛链接:http://www.zhihu.com/question/27069588/answer/38417756来源: ...
- JDBC(3)—ResultSet结果集
简介:ResultSet:结果集.封装了使用JDBC进行查询的结果.Statement只能进行更新操作,所以使用ResultSet进行查询操作. 1.调用Statement对象的executeQuer ...
- 绘图 Painter转接口封装的方式
记录下思想 适用于业务逻辑相对单纯的一些画法,比如画背景(颜色,背景,边框等) 一个Draw方法中如果绘制比较复杂的话,就会导致代码混乱,而不灵活,每次需求更改就得重新画过,可重用性差. 以接 ...
- C# 备份、还原、拷贝远程文件夹
最近一直都很忙,非常抱歉好久没有写过博客了.最近遇到拷贝远程文件的一些工作,比如我们发布的web站点的时候,开发提供一个zip压缩包,我们需要上传到远程的服务器A,然后在部署(文件拷贝)到远程环境B和 ...
- Android APK反编译详解(附图) (转)
这段时间在学Android应用开发,在想既然是用Java开发的应该很好反编译从而得到源代码吧,google了一下,确实很简单,以下是我的实践过程. 在此郑重声明,贴出来的目的不是为了去破解人家的软件, ...
- pytorch中检测分割模型中图像预处理探究
Object Detection and Classification using R-CNNs 目标检测:数据增强(Numpy+Pytorch) - 主要探究检测分割模型数据增强操作有哪些? - 检 ...
- pyqt QFileDialog
from PyQt5 import QtWidgetsfrom PyQt5.QtWidgets import QFileDialog class MyWindow(QtWidgets.QWidget) ...
- 微信小程序- 提示不在以下合法域名列表中
第一次开发微信小程序时在访问后台数据时总是提示 提示上面问题主要有两个原因: 1.为配置安全合法域名列表: 微信小程序在开发时需要在官网配置固定的数据来源网站: 登录小程序平台中->设置: 图中 ...
- 4种事务的隔离级别,InnoDB怎样巧妙实现?
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/z50L2O08e2u4afToR9A/article/details/82186189 事务ACID ...
- Spring Cloud Netflix Eureka源码导读与原理分析
Spring Cloud Netflix技术栈中,Eureka作为服务注册中心对整个微服务架构起着最核心的整合作用,因此对Eureka还是有很大的必要进行深入研究. 本文主要分为四部分,一是对项目构建 ...