多态性和数据隐藏:基类是覆盖还是忽略派生类的访问限制?

Polymorphism and data hiding: Does a base class override or ignore a derived class' access restrictions?

本文关键字:派生 访问 隐藏 数据 基类 多态性 覆盖      更新时间:2023-10-16

请看下面的代码清单:

#include <iostream>
using namespace std;
class Base {
public:
    virtual void Message() = 0;
};
class Intermediate : public Base {
};
class Final : public Intermediate {
    void Message() {
        cout << "Hello World!" << endl;
    }
};
int main() {
    Final final;
    /* Wont work (obviously):
    Final* finalPtr = &final;
    finalPtr->Message();
    */
    // Works:
    Intermediate* finalPtr = &final; // or Base* finalPtr = &final;
    finalPtr->Message();
    return 0;
}

请注意以下内容:

    在抽象的基类中,纯虚函数message()是public的
  1. 中间类(也是抽象类)继承自类(message()函数在中间中是否仍然是公共纯虚的?)
  2. Final类继承自Intermediate类,且message()函数为private(默认)
  3. 在main中,创建了一个类型为Final的对象
  4. 创建一个指向最终对象的中间指针

问题:如果运行该程序,finalPtr->Message();行通过其私有成功调用Final Message() 函数的实现。这是怎么发生的?基类是否覆盖或忽略派生类的访问限制?

相关问题:关于上面的(2.),定义Intermediate类的正确方法是什么?是否需要从基类中重新声明纯虚函数message() ?要记住,中间类并不打算提供实现。

注意:代码在数字火星编译器(dmc)和微软的Visual Studio编译器(cl)中测试过,在

中都能正常工作

这是怎么发生的?基类是否覆盖或忽略派生类的访问限制?

使用Public继承,基类的所有公共成员都成为派生类的公共成员。因此,Message()Intermediate中的公共功能。

函数在基类(Intermediate)指针上被调用,函数在基类中是公共的。动态调度(i。(对派生类函数的实际调用)只发生在运行时,因此这是有效的。

以上是由于在运行时,访问说明符没有意义,访问说明符规则只在编译时被解析和有效。

如果你在派生类指针上调用函数,那么在编译时编译器检测到Message()Final中被声明为private,因此它给出了错误。


当从抽象类派生时,派生类必须为基类的所有纯虚函数提供定义,否则将导致派生类也成为抽象类。

这里的Intermediate类是一个抽象类,只要你不需要创建这个类的对象,它就会工作得很好。注意,您可以创建一个指向抽象类的指针。

在c++中,虚拟说明符和访问说明符是互斥的。这就是为什么在c++中,对虚方法的访问可以缩小,而在c#或Java中这是不可能的。

当你试图通过基类指针访问虚函数时,编译器会编译代码,因为基类的虚函数是public的。

在注释的代码中,通过Final类指针调用访问受限的虚函数。因此会出现编译错误。