给出以下代码:
#include <iostream>
using std::cout;
using std::endl;
class classA {
virtual void virtualMethod() {
cout << "classA" << endl;
}
public:
virtual ~classA() {
virtualMethod();
}
void mA() {
virtualMethod();
}
};
class classB: public classA {
void virtualMethod() override {
cout << "classB" << endl;
}
public:
~classB() override {
virtualMethod();
}
void mB() {
virtualMethod();
}
};
int main(void) {
classA* obj = new classB;
obj->mA();
obj->mB(); // *** why I really get here error?
delete obj;
return 0;
}
我很乐意了解main中存在的任何行中发生的情况,以及在obj
函数的最终运行中删除main
时发生的情况。我不想知道答案:&#34;输出是......&#34;但是,要理解为什么会如此。
我的问题主要是了解mA
方法的情况。我们去哪里?我们似乎应该转到classA::virtualMethod
,因为classB::virtualMethod
是classB
的私有方法,因此,我们不会从classA
遇到它(但我运行代码,我发现它不正确,我不明白为什么)。
另外,根据编译器的说法,我很乐意理解为什么我在行obj->mB();
中出错了,原因是:
&#39;班级A&#39;没有名为&#39; mB&#39;
但是为什么它根据classB
不行(毕竟我们做过new classB
)。
答案 0 :(得分:4)
成员名称可见性基于对象或指针的声明的类型。由于obj
被声明为ClassA*
类型,因此只有ClassA
中的成员名称可见。在课外,只有公众成员可见。
这是因为指向ClassA
的指针可以指向基类的对象或其任何派生类。允许您调用obj->mB()
是没有意义的,因为obj
实际上可能不会指向具有mB()
成员函数的对象。我们必须能够在编译时确定名称是否有效,并且只能依赖于类型声明,而不是值。
虚拟方法的规则仅在允许可见性之后才会发挥作用。通过指针调用虚方法时,它使用它指向的对象的实际类型来查找要调用的方法。在运行时,它会在派生树中找到定义方法的最派生类,并使用它。
答案 1 :(得分:0)
virtualMethod
中的私有classB
可通过classA
中的任何功能访问,因为它在virtual
中标记为classA
(请注意Java不允许这样做,但C ++确实如此。
obj
是classA
类型的指针。 classA
不的方法有mB
,virtual
或其他方法,因此无法通过该指针访问。