避免在构造函数中调用虚方法(Do not call overridable methods in constructors)

CLR中说道,不要在构造函数中调用虚方法,原因是假如被实例化的类型重写了虚方法,就会执行派生类型对虚方法的实现。但在这个时候,尚未完成对继承层次结构中所有字段的初始化。所以,调用虚方法会导致不可预测的行为。归根结底,这是由于调虚方法时,直到运行时之前,都不会选择执行该方法的实际类型。

在MSDN中,也给我我们详细的提示和范例。

https://msdn.microsoft.com/en-us/library/ms182331.aspx

那我们就亲手来测试一下,新建两个类,Perople类,Chinese类,先不要看结果,看到下面这两个类,想想在实例化Chinese的时候,会是什么输出结果呢?

 1  public class People
 2     {
 3         public People()
 4         {
 5             PeopleSayHello();
 6         }
 7
 8         public virtual void PeopleSayHello()
 9         {
10             Console.WriteLine("hello");
11         }
12     }
public class Chinese : People
    {
        private bool HaveAbility { get; set; }

        public Chinese()
        {
            HaveAbility = true;
        }

        public override void PeopleSayHello()
        {

            Console.WriteLine((HaveAbility?"有":"没有")+"能力说你好");
        }
    }

接下来来看调用和输出结果吧:

是不是和你在脑海里运行的结果相同?

其实原因在第一句话中已经说的比较清晰了,更通俗的说就是在派生类实例化的时候,如果没有显式调用基的任意一个构造函数,那么默认选择基类的无参构造。所以在本例中,实例化Chinese的时候,首先执行了基类的无参构造。

和实例构造器初始化的顺序也相关,在创建实例的时候,首先为数据字段分配内存,然后初始化对象附加字段,包括类型对象的指针引用,最后才调用类型的构造函数设置对象的初始状态。

时间: 2024-10-23 02:01:36

避免在构造函数中调用虚方法(Do not call overridable methods in constructors)的相关文章

在基类构造器中调用虚方法需谨慎

最近,在基类的构造函数中调用虚方法时,发现了一个问题.先把问题重现如下: class Program { static void Main(string[] args) { var c = new Chinese(18); Console.ReadKey(); } } public class People { public int Age { get; protected set; } protected People() { this.Say(); } public virtual void

C++构造函数中调用虚函数

谈谈关于构造函数中调用虚函数的情况,仅讨论单继承,不考虑虚拟继承和多重继承. 测试平台:VS2013 + Win7X64 一个例子: #include <stdlib.h> #include <stdio.h> class Base { private: int __data; public: Base() { this->Func(); } public: virtual void Func() { printf("Base::Func"); } };

C++中构造函数能调用虚函数吗?(答案是语法可以,输出错误),但Java里居然可以

环境:XPSP3 VS2005 今天黑总给应聘者出了一个在C++的构造函数中调用虚函数的问题,具体的题目要比标题复杂,大体情况可以看如下的代码: [cpp] view plain copy class Base { public: Base() { Fuction(); } virtual void Fuction() { cout << "Base::Fuction" << endl; } }; class A : public Base { public:

EC笔记,第二部分:9.不在构造、析构函数中调用虚函数

9.不在构造.析构函数中调用虚函数 1.在构造函数和析构函数中调用虚函数会产生什么结果呢? #include <iostream> using namespace std; class cls1{ public: cls1(){ newMake(); }; ~cls1(){ deleteIt(); }; virtual void newMake(){ cout<<"cls1 make"<<endl; } virtual void deleteIt()

在构造函数和析构函数中调用虚函数------新标准c++程序设计

在构造函数和析构函数中调用虚函数不是多态,因为编译时即可确定调用的是哪个函数.如果本类有该函数,调用的就是本类的函数:如果本类没有,调用的就是直接基类的函数:如果基类没有,调用的就是间接基类的函数,以此类推.例如: #include<iostream> using namespace std; class A { public: virtual void hello(){cout<<"A::hello()"<<endl;} virtual void

条款9:绝不要在构造以及析构函数中调用虚函数

在构造以及析构函数期间不要调用virtual函数,因为这类调用从不下降到derived class中.例如说下面这个例子: 1 class Transaction{ 2 public: 3 Transaction(); 4 virtual void logTransactions()s const = 0; 5 //... 6 }; 7 Transaction::Transaction() 8 { 9 //... 10 logTransaction(); 11 } 12 class BuyTra

Effective JavaScript Item 38 在子类构造函数中调用父类构造函数

本系列作为Effective JavaScript的读书笔记. 在一个游戏或者图形模拟的应用中,都会有场景(Scene)这一概念.在一个场景中会包含一个对象集合,这些对象被称为角色(Actor).而每个角色根据其类型会有一个图像用来表示,同时场景也需要保存一个底层图形展示对象的引用,被称为上下文(Context): function Scene(context, width, height, images) { this.context = context; this.width = width

09 构造函数能调用虚函数吗?

[本文链接] http://www.cnblogs.com/hellogiser/p/whether-constructor-can-call-virtual-function.html [题目] 构造函数可以调用虚函数吗?语法上通过吗?语义上可以通过吗? [分析] 构造函数调用虚函数(virtual function),语法上可以通过(程序可以正常执行),但是语义上通不过(执行结果不是我们想要的) 请看以下代码 C++ Code 12345678910111213141516171819202

基类中的虚方法到底有什么作用?

只有基类的方法加上关键字virtual后才可以被override,从而实现面向对象最重要的特征--多态性,即基类可以使用派生类的方法. C#中指出:普通的方法重载:指的是类中两个以上的方法(包括隐藏的,继承而来的方法)取的名字相同,只要使用的参数类型或者参数个数不同,编译器便知道在何种情况下应该调用哪个方法.   而在派生类中重新定义此虚函数时要求的是:方法名称.返回值类型.参数表中的参数个数.类型.顺序都必须与基类中的虚函数完全一致. 简单一点说就是子类中override的方法能够覆盖积累中的