多态性和数据隐藏:基类是覆盖还是忽略派生类的访问限制?
Polymorphism and data hiding: Does a base class override or ignore a derived class' access restrictions?
请看下面的代码清单:
#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的
- 中间类(也是抽象类)继承自基类(message()函数在中间中是否仍然是公共纯虚的?)
- Final类继承自Intermediate类,且message()函数为private(默认)
- 在main中,创建了一个类型为Final的对象
- 创建一个指向最终对象的中间指针
问题:如果运行该程序,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类指针调用访问受限的虚函数。因此会出现编译错误。
- 如何使用单独文件中的派生类访问友元函数对象
- 为什么此派生对象无法访问基类的后递减方法?
- C++:为什么无法在派生类中访问受保护的构造函数?
- 如何使用 C++ 中的继承函数访问派生类中的局部变量
- 派生的 wxPanel 控件如何访问其中包含 wxDialog 中的数据?
- 从纯虚拟类 (A) 派生的指针无法访问来自纯类 (B) 的重载方法
- C ++基础私有方法在将自身转换为派生类后可以访问吗?
- 按基类对象访问派生类资源时出错
- 使(虚拟)函数在大多数派生类中无法访问中间基类中可访问,定义良好?
- 从模板化父类中的派生内部类访问受保护的成员变量
- 如何从派生类访问基类中的重载运算符?
- 两个抽象类,派生自同一个基类.如何访问从一个抽象类到另一个抽象类的指针
- C++11: 如何访问派生类中的基类成员?
- 访问派生类的 QMetaObject
- 使用基类对象访问派生的仅类方法
- 如何在 c++ 中通过基类引用访问派生类的对象?
- 派生类无法访问基类的受保护成员
- 如何在 c++ 中使用多态性访问派生类字段?
- 为了访问方法,从基类动态转换为派生类
- C++继承从基类指针访问派生类中的非虚拟函数