虚函数仅在使用间接时调用 - 经典早期绑定问题?

时间:2017-03-03 21:11:11

标签: c++ inheritance

我有三种不同的接口实现(求解方程组)。旧接口本质上是一个类中的void foo(int *f)。现在我想将此概括为我同时解决N系统的情况。为此我想要接口void foo(int *f[N])。

在代码库中有一个定义接口的抽象类,然后从该类派生出三个类。我想在不破坏现有代码的情况下添加我的概括。因此,我想添加新接口并将旧接口委托给新接口。这是我的压缩版本:

#include <iostream>

struct AbstractClass {
    /// Old interface, needs to be retained.
    virtual void foo(int *f) {
        std::cout << "AbstractClass::foo(int *f)\n";
        int *a[2] = {f, nullptr};
        foo(a);
    }

    /// New interface.
    virtual void foo(int *f[2]) {
        std::cout << "AbstractClass::foo(int *f[2])\n";
    }
};

struct Derived : public AbstractClass {
    /// New interface.
    void foo(int *f[2]) override {
        std::cout << "Derived::foo(int *f[2])\n";
    }
};

int main(int argc, char **argv) {
    // Code using the old interface.
    Derived d;
    int *a;
    d.foo(a);
}

Work with the code

我希望d.foo(a)的电话会转到继承的Derived::foo(int *f),然后转到Derived::foo(int *f[2])。但是,g++ 6.3给出了以下内容(在C ++ 11模式下):

inheritance-test.cpp: In function 'int main(int, char**)':
inheritance-test.cpp:31:12: error: no matching function for call to 'Derived::foo(int*&)'
     d.foo(a);
            ^
inheritance-test.cpp:21:10: note: candidate: virtual void Derived::foo(int**)
     void foo(int *f[2]) override {
          ^~~
inheritance-test.cpp:21:10: note:   no known conversion for argument 1 from 'int*' to 'int**'

看起来派生对象并没有真正继承我想要的方法。

使用运行时多态性和指向基类的指针确实有效:

AbstractClass *pd = new Derived();
int *a = nullptr;
pd->foo(a);
delete pd;

我真的不明白为什么没有指针它不起作用。 vtable不与自动存储一起使用,因为函数调用在编译时绑定(早期绑定)?

这让我更接近解决方案,但我仍然需要触摸使用此库的所有代码。然而,这不是一个真正的选择,旧的东西必须继续工作。

我该怎么办(除了复制所有代码)?将此委托复制到每个派生类中是否足够?

1 个答案:

答案 0 :(得分:2)

C ++中有一些称为name hiding的东西。基本上,当您在派生类中重写成员函数时,它会隐藏在基类中找到的所有其他重载。

这就是下面失败的原因:

Derived d;
int *a;
d.foo(a);

以下作品:

AbstractClass *pd = new Derived();
int *a = nullptr;
pd->foo(a);

因为带有指针的foo的重载位于AbstractClass但隐藏在Derived中。

您可以使用using显示这些重载。

struct Derived : public AbstractClass {

    using AbstractClass::foo;
    void foo(int *f[2]) override {
        std::cout << "Derived::foo(int *f[2])\n";
    }
};

Demo