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

时间:2011-10-10 07:12:09

标签: c++ oop inheritance

请查看以下代码清单:

#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;
}

请注意以下事项:

  1. 在抽象基础类中,纯虚函数 message()是公开的
  2. 中级类(也是抽象的)继承自基础类(消息()函数是否在中级<中保持公共纯虚拟/强>?)
  3. 最终类继承自中级类, message()函数属于私有(默认情况下)
  4. 主要是创建最终类型的对象
  5. 创建最终对象的中级指针
  6. 问题: 如果您运行该程序, finalPtr-&gt; Message(); 行成功调用最终 message()功能实现的私有即可。这是怎么发生的?基类是否覆盖或忽略派生类的访问限制?

    相关问题: 关于上面的(2.),定义中级类的正确方法是什么?是否需要从基类重新声明纯虚函数 message(),同时请注意中级类不是为了提供实现。

    注意:代码已使用Digital Mars Compiler(dmc)和Microsoft的Visual Studio编译器(cl)进行测试,并且在两者中都运行良好

2 个答案:

答案 0 :(得分:4)

  

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

使用公共继承,Base类的所有公共成员都将成为派生类的公共成员。是的Message()Intermediate中的公共功能。

在基类(Intermediate)指针上调用该函数,该函数在基类中是公共的。动态调度(即对Derived类函数的实际调用)仅在运行时发生,因此可以正常工作。

上述原因是在运行时,访问说明符没有意义,访问说明符规则只在编译时解析并生效。

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


从Abstract类派生时,派生类必须 ALL 提供Base类的Pure虚函数的定义,否则将导致Derived class也是一个抽象类。

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

答案 1 :(得分:1)

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

当您尝试通过基类指针访问虚函数时,编译器会编译代码,因为基类的虚函数是公共的。

在您的注释代码中,具有受限访问权限的虚拟函数通过Final类指针调用。因此编译错误。