5. 显式调用父类的成员函数

在有继承关系的类中,一旦子类对父类同一个成员函数进行了覆盖,则子类对象以默认调用的一定是子类的成员函数,而父类的成员函数则被覆盖(屏蔽)。如果再子类成员函数中需要显示调用父类的成员函数,则需要使用类名和作用域限定符(::)来显式的调用被覆盖的成员函数。

语法

class 子类名: public 父类名 {
    返回类型 成员函数名(形式参数列表) {
        //  调用父类的成员函数(用父类名指定名字空间)
        父类名::成员函数名(实际调用参数列表)
    }
};

示例

// filename: call_demo.cpp
#include <iostream>

#define PI (3.1415926)
// 点类(描述一个点的位置,面积等信息)
class Point {
    public:
        Point(float ax=0, float ay=0):x(ax), y(ay) {
            std::cout << "Point(" << x << "," << y << ")\n";
        }
        void info(void) {
            std::cout << "点(" << x << "," << y << ")\n";
        }
        void moveTo(float new_x, float new_y) {
            x = new_x; y = new_y;
        }
        float getArea(void) {
            return 0;
        }
    protected:
        float x;
        float y;
};
// 圆类(描述圆的位置、半径、面积等信息)
class Circle : public Point {
    public:
        Circle(float ax, float ay, float radius)
            : Point(ax, ay), r(radius) {
            //  x = ax; y = ay; r = radius;
            std::cout << "Circle(" << x << "," << y << "," << r << ")\n";
        }
        void info(void) {
            std::cout << "圆(" << x << "," << y << "," << r << ")\n";
        }
        void showBaseInfo(void) {
            // 显式调用Point类的info 而非自己的info函数
            Point::info();
        }
        float getArea(void) {
            return PI*r*r;
        }
    protected:
        float r;  // 半径
};

int main(int argc, char * argv[]) {
    Point p1(3, 5);
    Circle c1(4, 6, 10);

    c1.info();
    p1.info();
    p1.moveTo(100, 105);
    // 子类对象不存在moveTo,则调用父类的方法
    c1.moveTo(200, 210);
    p1.info();
    c1.info();
    c1.showBaseInfo();
    std::cout << "程序结束!" << std::endl;
    return 0;
}

编译和运行结果如下

weimz@mzstudio:~$ g++ -o call_demo call_demo.cpp
weimz@mzstudio:~$ ./call_demo
Point(3,5)
Point(4,6)
Circle(4,6,10)
圆(4,6,10)
点(3,5)
点(100,105)
圆(200,210,10)
点(200,210)
程序结束!

从上述结果可以看出 c1.showBaseInfo(); 实际打印的是 点(200,210),此成员函数调用的是 Point::info 成员函数。

实验

自己写一个显式调用被覆盖的父类成员函数的示例。