虚方法
在基类和派生类里声明相同的函数原型,使用关键字virtual,称为虚方法。
class Brass
{
private:
...
public:
virtual void ViewAcc ();
...
}
class BrassPlus:public Brass
{
private:
...
public:
virtual void ViewAcc ();
...
}
基类版本的限定名为 Brass :: ViewAcc (),派生类版本的限定名为 BrassPlus :: ViewAcc ()。
虚方法选择
程序根据对象类型决定使用哪个版本:
Brass dom ();
BrassPlus dot ();
dom.ViewAcc (); //使用Brass :: ViewAcc ()
dot.ViewAcc (); //使用BrassPlus :: ViewAcc ()
如果方法是通过引用或指针(而不是对象)调用的, 如果没有关键字 virtual, 程序根据引用或指针的类型选择方法; 如果使用了关键字 virtual, 程序根据引用或指针指向的对象类型选择方法。
Brass dom ();
BrassPlus dot ();
Brass & b1_ref =dom;
Brass & b2_ref =dot;
1)如果没有关键字 virtual:
b1_ref.ViewAcc (); //使用Brass :: ViewAcc (),根据引用的类型 (Brass)
b2_ref.ViewAcc (); //使用Brass :: ViewAcc (), 根据引用的类型 (Brass)
2)如果使用了关键字 virtual:
b1_ref.ViewAcc (); //使用Brass :: ViewAcc (),根据引用对象 (dom为Brass) 的类型
b2_ref.ViewAcc (); //使用BrassPlus :: ViewAcc (), 根据引用对象 (dot为BrassPlus) 的类型
注:基类的引用和指针可以指向派生类对象,派生类的引用和指针不可以指向基类。派生类对象可以使用基类方法,基类类对象不可以使用派生类方法。
虚函数和构造/析构函数
构造函数不能是虚函数。创建派生类对象时,将调用派生类的构造函数,然后派生类的构造函数将使用基类的一个构造函数。派生类不继承基类的构造函数,不必将构造函数声明为虚拟的;
析构函数应当是虚函数。如果需要释放内存,派生类析构函数先释放派生类的组件,然后调用基类析构函数释放释放基类组件。
虚函数和友元
友元不能是虚函数,因为友元不是类成员。
隐藏方法
如果在派生类中重新定义函数,将隐藏同名的基类方法,不管参数特征标如何。如果重新定义继承的方法,应确保与原来的原型完全相同。
class Dwelling
{
public:
virtual void showperks(int a) const;
virtual void showperks(double a) const;
virtual void showperks() const;
...
}
class Hovel: public Dwelling
{
public:
virtual void showperks(int a) const;
virtual void showperks(double a) const;
virtual void showperks() const;
...
}
如果在派生类里只定义了一个版本,如只定义了 virtual void showperks() const;则另外两个版本showperks(int a) const 和 showperks(double a) const 将会被隐藏, 派生类对象不能使用它们。
Hovel trum;
trum. showperks(); //可以
trum. showperks(5); //不可以
C++ Primer Plus (13.4)