1.基类的非虚函数可以调用(纯)虚函数。例如:所有Shape类对象有个共同的方法print,print方法依赖area()方法,那么area方法可以是虚函数也可以是纯函数。前提是派生类不需要不同的print方法。
#include "Shape.hpp"
void Shape::print() const
{
float a = this->area(); // area() 为纯虚方法
// ...
}
2.使用虚函数的两种情况:
每一个派生类都有一个结构完全一样,只有一小块不同的方法。在这种情况下,你最好在基类写一个全面的算法作为public方法(有时是非虚的),然后在派生类中写那不同的一小块。这一小块在基类中声明(通常是protected:的,纯虚的,当然至少是virtual的),并且最终在每个派生类中被定义。
每一个派生类都有一个结构完全不同,但有一小块的大多数(如果不是全部的话)相同的方法。在这种情况下,你最好将全面的算法放在最终在派生类中定义的public: virtual之中,并且将一小块可以被只写一次的公共代码(避免代码重复)隐藏起来。一般放在基类的protected:部分。注意,由于public:用户不需要/不想做它们做的事情,如果在基类中隐藏它们,通常应该使它们是protected:的。假定它们是protected:的,那么可能不应该是virtual的。
上面两种情况并不互相排斥,可以同时使用。
3.如何使用protected virtuals 替代public virtuals
使用public virtuals的状况:
class Base {
public:
virtual void f(int x); ← may or may not be pure virtual
virtual void f(double x); ← may or may not be pure virtual
};
改进后使用protected virtuals 替代public virtuals的状况:
class Base {
public:
void f(int x) { f_int(x); } ← non-virtual
void f(double x) { f_dbl(x); } ← non-virtual
protected:
virtual void f_int(int);
virtual void f_dbl(double);
};
使用public overloaded virtuals的原则:
Public? Inline? Virtual? Overloaded?
Yes No Yes Yes
使用 Public Overloaded Non-Virtuals 调用Protected Non-Overloaded Virtuals的原则
Public? Inline? Virtual? Overloaded?
Yes Yes No Yes
No No Yes No
这样做的好处是基类稍微大些,但是派生类(对象)却轻便了许多。它给基类增加了隐藏的规则,派生类(对象)可以不管这些规则。