有没有其他方法可以防止派生类的超类方法被调用,而不是基类的方法,比如用关键字之类的?

问题描述 投票:2回答:1

我和几个同事一起练习C++的时候,其中一个人在派生类中 "经历了一个bug"。长话短说,他在调用基类方法(callFoo),他还以为是在打电话 A::Foo()但他得到了 B::Foo() 而不是。

这里有一个完整的例子,说明我其实是在问什么。我真的不知道怎么解释比这更好。我确实找到了一个解决方案,但是这个解决方案很尴尬,它使得代码有点难以 "消毒",以便于我们未来类的扩展。有没有其他的解决方案?(也许是一个关键字?)

n.b.这个例子纯粹是演示性的:在原来的例子中。callFoo() 是的 operator= 对于 Class A. 我尽量把它简化。

例1:不受欢迎的行为

#include <iostream>

class A{
    public:
        virtual void Foo(){
            std::cout<<"A Foo\n";
        }

        virtual void callFoo(){
            Foo();
        }
};

class B: public A{
    public:
        virtual void Foo() override{
            std::cout<<"B Foo\n";
        }
};


int main(){
    B mB;

    mB.Foo();
    mB.callFoo();

    return 0;
}

例2:非理想的修复方法;还有其他的解决方案吗?

class A{
    public:
        virtual void Foo(){
            std::cout<<"A Foo\n";
        }

        virtual void callFoo(){
            A::Foo();
        }
};
c++ c++11 overriding derived-class
1个回答
2
投票

很明显,你正在创建一个派生类的对象,并试图调用存在于基类中的callFoo()函数.我将尝试一步一步地可视化这个问题。

  1. B mB --> 由于我们正在创建一个 衍生类对象 జజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజ VPtr 将指向 Vtable 的派生类。
  2. mB.callFoo(); --> 衍生类的。Vptr 还在指着 VTable 由于对象试图调用callFoo(),所以它没有在衍生类的 衍生类别表 .它调用了Base类的callFoo()。现在这里是主要的陷阱 ,Foo()是从callFoo()的主体中调用的,但同样如前所述,它将在 VTable 的派生类,因此它将调用派生类Foo()。

因此,我们需要明确地告诉编译器,我们需要基本版本的方法,并使用 A::Foo() 来调用Base类方法。

关于VTable和VPtr的更多细节,在stack-overflow中有一个有用的链接。VPtr和VTable的深度C++

© www.soinside.com 2019 - 2024. All rights reserved.