C++开发中级


847 浏览 5 years, 4 months

6.3 重写方法时的特殊情况

版权声明: 转载请注明出处 http://www.codingsoho.com/

重写方法时的特殊情况

当重写方法时,需要注意几种特殊情况。 本节将列出您可能遇到的一些情况。

1.静态超类方法

在C++中,无法重写静态方法。对于多数情况而言,知道这一点就足够了。然而,在此您需要了解一些推论。

首先,方法不可能既是静态的又是虚的。出于这个原因,试图重写一个静态方法得到的结果并非您的预期。如果子类中存在的静态方法与超类中的静态方法同名,实际上这是两个独立的方法

下面的代码显示了两个类,这两个类刚好都具有一个名为beStatic()的静态方法。这两个方法毫无关系。

class SuperStatic{
    public:
        static void beStatic(){
            cout << "SuperStatic being static." << endl;
        }
};

class SubStatic{
    public:
        static void beStatic(){
            cout << "SubStatic keepin' it static." << endl;
        }
};

由于静态方法属于类,调用两个类的同名方法时将调用各自的方法。

SuperStatic::beStatic();
SubStatic::beStatic();

输出为:

SuperStatic being static.
SubStatic keepin' it static.

当用类访问这些方法的时候一切都很正常。当涉及到对象时,这一行为就不是那么明显。在C++中,可以使用对象调用静态方法,但由于方法是静态的因此没有this指针,也无法访问对象本身,因此使用对象调用静态方法等价于使用classname::method()调用静态方法。回到前面的示例,您可以编写如下的代码,但是结果令人惊讶:

    SubStatic mySubStatic;
    SuperStatic & ref = mySubStatic;
    mySubStatic.beStatic();
    ref.beStatic();

beStatic()的第一次调用显然调用SubStatic版本,因为调用它的对象显式地声明为SubStatic。第二个调用的运行方式可能并非您预期的那样。这个对象是一个SuperStatic引用,但指向的是一个SubStatic对象。在此情况下,会调用SuperStatic版本的beStatic()。原因是当调用静态方法时,C++不关心对象实际上是什么,只关心编译时类型。在此情况下,该类型为SuperStatic的引用。

有的编译器会阻止这种赋值,错误如下

[Error] invalid initialization of reference of type 'SuperStatic&' from expression of type 'SubStatic'

前面示例的输出如下:

SubStatic keepin' it static.
SuperStatic being static.

静态方法属于定义它的类名称,而不属于特定的对象。当类中的方法调用静态方法时,所调用的版本是通过正常的名称解析来决定的。当使用对象调用时,对象实际上并不涉及调用,只是用来判断类型。

参考代码 SubOverrideMethodStatic.cpp

2.超类方法被重载

当指定名称以及一组参数重写某个方法时,编译器隐式地隐藏超类中的同名方法的所有其他实例。其想法为:如果您重写了给定名称的某个方法,可能是想重写所有的同名方法,您只是忘记这么做了,因此应该作为错误处理。这是有意义的,您可以这么考虑——为什么您想要修改方法的某些版本而不修改其他版本呢?考虑下面的子类,这个子类重写了一个方法而没有重写相关的重载方法: