一道虚函数题目引发的血案

对多态不了解的可以先大致了解下:多态的实现及原理

C++的多态性用一句话概括就是:在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数。如果对象类型是派生类,就调用派生类的函数;如果对象类型是基类,就调用基类的函数

  1:用virtual关键字申明的函数叫做虚函数,虚函数肯定是类的成员函数。  

  2:存在虚函数的类都有一个一维的虚函数表叫做虚表,类的对象有一个指向虚表开始的虚指针。虚表是和类对应的,虚表指针是和对象对应的。  

  3:多态性是一个接口多种实现,是面向对象的核心,分为类的多态性和函数的多态性。  

  4:多态用虚函数来实现,结合动态绑定.  

  5:纯虚函数是虚函数再加上 = 0;  

  6:抽象类是指包括至少一个纯虚函数的类。

Q1:哪些函数不能被定义为虚函数

A1:虚函数必须是类的非静态成员函数,前面加virtual修饰;他是在程序运行(强调动态)的时候匹配各个对象合适的成员函数。定义了虚函数后可以在派生类中重新定义该虚函数,但是要求参数个数、类型、返回值一致。以实现统一的接口,如果没有重新定义该函数,则继承其基类的虚函数。

虚函数可以实现多态,但下面这些函数不能声明为虚函数:

  1. 普通的函数:普通函数只能被overload,不能被override,也不能被继承,所以在编译的时候就绑定函数,所以不能声明为virtual,没有意义!
  2. 构造函数:构造函数用来确定初始化对象的,而virtual是为了在不了解具体的情况下实现动态绑定,调用不同类型中合适的成员函数而存在的,对象都没有产生的情况下不能实现多态。
  3. 内联函数:inline函数在编译时被展开,在调用处将整个函数替换为代码块,省去了函数跳转的时间,提高了SD,减少函数调用开销。而virtual是在运行期间才能动态绑定,这决定了inline函数不可能为虚函数。
  4. 静态成员函数:静态成员函数是类的组成部分,但是不是任何对象的组成部分,所有对象共享一份,没有必要动态绑定,也不能被继承。
  5. 友元函数:friend函数不是类的成员函数,c++不支持友元被继承。

能是虚函数的条件:

  1. 是类的成员函数
  2. 能被继承
  3. 动态编译绑定,动态;迟联编译

Q2: 析  构函数定义为虚函数的作用

A:  当基类指针指向派生类对象实现多态时,如果基类析构函数不是虚函数,则编译器实施静态绑定,在删除基类指针时,只会调用基类的析构函数,而不调用派生类析构函数,造成派生类对象析构不完全,造成内存泄漏。

 

Q3:那为什么析构函数不默认为虚函数呢

A:原因时虚函数表的开销以及C语言的类型的兼容性。有虚函数表的对象总是在开始的位置包含一个隐含的虚函数表指针成员,如果时对于MFC类CPoint和CSize这样的小型类,增加一个指针就增加了很多内存占用,而且是的其内存表示和基类POINT和SIZE不一致。

Q4:假设a是基类,b是派生类

b bb;bb.fun();如何找到fun()函数?

A:一个类的普通成员函数存放在代码段里,不占用类空间;所以类的成员函数对于类来讲,一方面是逻辑上的“属于”,一方面是物理上的“不依赖”。直接去代码段去找fun()函数,找到就执行。

Q5:a* bb = new b();bb->fun();若fun()函数是虚函数,调用的是哪个fun()函数

A:先判断bb的类型,是a*类型。一个对象的虚函数表里有什么,在创建对象的时候就确定了。具体过程:

a* bb = new b();bb构造的时候先构造基类,这时候虚函数表已经被建立,但此时虚函数表里存放的函数指针仍然指向基类a的fun函数地址。然后基类部分构造完全之后构造子类,然后因为fun()是virtual函数,子类重写了fun()函数,并让基类a的虚函数表里指向a的fun地址的函数指针,指向子类b的fun函数地址,即子类的fun()地址覆盖了父类的fun()地址。所以当父类的指针指向子类对象时,虽然时父类的指针,会以父类的方式寻找fun()的地址,但是此时真正找到的fun()的地址已经在构造的时候被子类的fun()的地址所覆盖。也就是说,若子类不重写fun函数,这时候fun的地址并不会被覆盖,调用的仍然时父类的fun函数。这也就是多态的实现机制。

Q6: a* bb = new b();与b* bb = new b();的区别?

A:???写到这里突然傻逼了改天补上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值