C++:多态公有继承中的虚方法

Posted 赵同学的代码时间

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++:多态公有继承中的虚方法相关的知识,希望对你有一定的参考价值。

派生类对象可以使用基类的方法,而未作任何修改,但是,某些情况下,我们会希望同一个方法在派生类中和基类中具有不同的功能,即,方法的行为应该取决于调用方法的对象,我们把这种较复杂的行为称为多态(顾名思义,具有多种形态)。


在C++中提供了两种机制可用于多态公有继承:

a. 在派生类中,重新定义基类方法

b. 使用方法


本文着重介绍方法b,使用虚方法实现多态公有继承。


虚 —— virtual

定义虚方法的关键字为virtual,在被定义成员函数的最前(返回类型前)加上该关键字,该方法则被定义为虚方法。请注意,虚方法与纯虚函数是不同的两个概念。


如果方法是通过引用或指针而不是对象进行调用,是否为虚方法将使得C++选择调用功能时发生差异。


如果没有使用虚函数标记virtual,程序将根据引用类型或指针的定义类型,选择调用方法,如果使用了虚函数标记virtual,程序将根据引用类型或指针指向的真实类型,选择调用方法。


Classname1 dom;Classname2 dot;//Classname2 由 Classname1 派生 且 存在虚方法show();
//由于存在虚方法,c1,c2按照指向类型去调用Classname1 & c1 = dom;Classname1 & c2 = dot;c1.show();// 调用 dom 类型的show();c2.show();// 调用 dot 类型的show();
//倘若不存在虚方法,将按照c1,c2的定义类型去调用c1.show();// 调用 Classname1 类型的show();c2.show();// 调用 Classname1 类型的show();


在基类中已经声明为虚方法,派生类中无论是否声明为虚方法,程序均会判定为虚方法,但为了便于阅读,建议都加上虚方法关键字virtual。


在基类中未定义为虚方法,在派生类中重新定义为虚方法,使用指向派生类的指针去调用该函数,程序并不会将其判定为虚成员函数。


总结 : 虚方法的声明是 向下兼容但向上不兼容的。


来自CSDN的测试实例:

以a指针类型指向派生类b时,调用M成员函数,由于A中M非虚方法,虽然B中声明M为虚方法,但程序还是调用了指针定义类型的成员函数,即基类中的方法M,说明,B中的声明对于该问题时是无效的。但如果以B作为基类,我们可以发现,无论M还是P成员函数,都被程序识别为虚方法,调用了指针指向的真实类型的成员函数。


虚析构函数

当理解了上述虚方法的实现特性后,我们便能更好的理解虚析构函数的必要性,倘若基类未定义一个虚析构函数,那么,我们使用指针或引用方法调用析构函数时,只会去调用指针定义类型的析构函数,倘如析构函数还需执行其他的功能,派生类中的析构函数就会被忽略,可能在实际调用中产生错误,因此,使用虚析构函数,是相当必要的,即使该虚构函数不需要执行任何操作。


有关虚函数的其他注意事项

关于虚函数的实现,静态动态联编,虚函数表等问题,将以后再谈,这里,再提示几个有关虚函数是其他注意事项。


  • 要在派生类中重新定义基类的方法,则将它设置为虚方法,否则设置为非虚方法,这是由于静态联编和动态联编在效率上的考量;

  • 在基类方法的声明中使用关键字virtual可以使该方法在基类及所有派生类(包括派生类派生类)都是虚方法;

  • 如果使用指向对象的引用或指针来调用虚方法,程序将依照虚方法规则选择调用的方法,这称为动态联编,这使得基类指针或引用可以指向派生类对象;

  • 如果定义的类将被用作基类,则应将那些要在派生类中重新定义的类方法声明为虚的。

以上是关于C++:多态公有继承中的虚方法的主要内容,如果未能解决你的问题,请参考以下文章

C++多态(下)

9-4:C++多态之单继承和多继承中的虚函数表

C++多态

C++之多态总结(多态的定义及实现,抽象类,多态原理,单继承,多继承中的虚函数表)

C++多态

C++——多态