将虚拟方法定义为私有时会发生什么?

时间:2018-06-14 07:54:56

标签: c++ c++11 polymorphism virtual-functions

给出以下代码:

#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::virtualMethodclassB的私有方法,因此,我们不会从classA遇到它(但我运行代码,我发现它不正确,我不明白为什么)。

另外,根据编译器的说法,我很乐意理解为什么我在行obj->mB();中出错了,原因是:

  

&#39;班级A&#39;没有名为&#39; mB&#39;

但是为什么它根据classB不行(毕竟我们做过new classB)。

2 个答案:

答案 0 :(得分:4)

成员名称可见性基于对象或指针的声明的类型。由于obj被声明为ClassA*类型,因此只有ClassA中的成员名称可见。在课外,只有公众成员可见。

这是因为指向ClassA的指针可以指向基类的对象或其任何派生类。允许您调用obj->mB()是没有意义的,因为obj实际上可能不会指向具有mB()成员函数的对象。我们必须能够在编译时确定名称是否有效,并且只能依赖于类型声明,而不是值。

虚拟方法的规则仅在允许可见性之后才会发挥作用。通过指针调用虚方法时,它使用它指向的对象的实际类型来查找要调用的方法。在运行时,它会在派生树中找到定义方法的最派生类,并使用它。

答案 1 :(得分:0)

virtualMethod中的私有classB可通过classA中的任何功能访问,因为它在virtual中标记为classA(请注意Java不允许这样做,但C ++确实如此。

objclassA类型的指针。 classA 的方法有mBvirtual或其他方法,因此无法通过该指针访问。