虚函数小结
1) 虚函数是动态绑定的,也就是说,使用虚函数的指针和引用能够正确找到实际类的对应函数,而不是执行定义类的函数。这是虚函数的基本功能,就不再解释了。
2) 构造函数不能是虚函数。而且,在构造函数中调用虚函数,实际执行的是父类的对应函数,因为自己还没有构造好, 多态是被disable的。
3) 析构函数可以是虚函数,而且,在一个复杂类结构中,这往往是必须的(delete 指向子类的父类指针时,不会析构子类)。
4) 将一个函数定义为纯虚函数,实际上是将这个类定义为抽象类,不能实例化对象。(与第5点结合)
5) 纯虚函数通常没有定义体,但也完全可以拥有。
6) 析构函数可以是纯虚的,但纯虚析构函数必须有定义体,因为析构函数的调用是在子类中隐含的。
7) 非纯的虚函数必须有定义体,不然是一个错误。
8) 派生类的override虚函数定义必须和父类完全一致。除了一个特例,如果父类中返回值是一个指针或引用,子类override时可以返回这个指针(或引用)的派生。例如,在上面的例子中,在Base中定义了 virtual Base* clone(); 在Derived中可以定义为 virtual Derived* clone()。可以看到,这种放松对于Clone模式是非常有用的。
9)基类private纯虚函数:在C++中virtual表示多态,public、protected和private表示访问权限(),它们是正交的两个概念(java不同)
实际使用场景:
当你实现一个算法的时候,通常不希望将实现信息暴露给外部和给外部使用,包括将会被继承的类。但是,算法有要有扩充性,可以针对不同的信息实现不同的结果。怎么办?私有的虚函数:这个函数只有我可以使用,但是却能够迟后决定调用的具体函数。从而在封装上和扩展性能上都有比较好的性能
a.纯虚函数可以设计成私有的,不过这样不允许在本类之外的非友元函数中直接调用它,子类中只有覆盖这种纯虚函数的义务,却没有调用它的权利
b.虚函数的重载性和它声明的权限无关(c++ primarily)
c.虚函数是通过虚表来实现的。虚表可以理解为一个函数指针数组,编译器会根据函数名称和原型找到对应函数在虚表中的index. 派生类可能override了基类的实现,这样只是虚表中的函数指针变了,索引并没变。又因为是通过基类的指针调用的,访问权限也是按照基类的。很简单的东西,要解释清楚却很费事 :)
d.这个问题与多态实现机制无关,试图从虚表角度去解析的行为不过是自我形成的错觉。真正也是唯一的原因是:可访问性是静态解析的,不是动态解析的。即是说,无论最终覆盖者的可访问性如何,可访问性均取决于函数调用后缀表达式的可访问性。派生类中虚函数的访问权限是在编译阶段由基类确定的,在运行阶段不再检查访问权限,所有,虚函数的访问权限与派生类就没关系了
e.d.结论
=====以下待验证
纯虚函数的在派生类中的实现不受限于它声明时的权限。
e. 提出问题:
1. 基类中公有虚函数是否可以被派生类protected或者private 覆盖?
答:可以,派生类可以访问基类公有虚函数,故可以实现覆盖。
2. 基类中私有纯虚函数是否可以被派生类public 覆盖?
答:不可以,派生类不能访问基类私有虚函数。
————————————————
版权声明:本文为CSDN博主「tjian2014」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/tjian2014/article/details/17301249
来源:CSDN
作者:Emiiya
链接:https://blog.csdn.net/woalss/article/details/103488272