【问题标题】:Unable to call pure abstract base class overload无法调用纯抽象基类重载
【发布时间】:2019-12-12 21:46:13
【问题描述】:

为什么以下代码无法编译,我该怎么办?不应该找到基类中声明的纯抽象方法吗?

#include <string>

using namespace std::string_literals;

struct A
{
    virtual void func1(int) = 0;
    virtual void func1(std::string) = 0;
};

struct B : A
{
    void func1(int) override
    {
        func1("bla"s);
    }
};

struct C : B
{
    void func1(std::string) override
    {
    }
};

error C2664: 'void B::func1(int)': cannot convert argument 1 from 'std::string' to 'int'

提前致谢, 马丁

编辑链接器错误!

如果有三个文件:

文件 test.h

#include <string>

using namespace std::string_literals;

struct A
{
    virtual void func1(int) = 0;
    virtual void func1(std::string) = 0;
};

struct B : A
{
    void func1(int) override
    {
        A::func1("bla"s);
    }
};

struct C : B
{
    void func1(std::string) override;
};

文件 test.cpp

void C::func1(std::string)
{

}

文件 main.cpp

int main()
{
    C c;

    return 0;
}

这导致

错误 LNK2019 未解析的外部符号 ""public: virtual void __thiscall A::func1(class std::basic_string,class std::allocator >)" (?func1@A@@UAEXV?$basic_string@DU?$char_traits @D@std@@V?$allocator@D@2@@std@@@Z)" in Funktion ""public: virtual void __thiscall B::func1(int)"

我正在使用 Visual C++ v140。

它适用于using A::func1;。有什么区别?

【问题讨论】:

  • A::func1("bla"s);using A::func1;B 定义内,因此可以通过 B 内的名称查找找到这两个重载
  • 缺少 B void func1(std::string) override = 0;

标签: c++ oop inheritance overloading abstract-class


【解决方案1】:

Bfunc1 实现隐藏了A 的其他两个重载。您可以通过以下方式将它们导入B的界面:

struct B
{
    using A::func1;
    /* ... */
};

一般中,您也可以直接调用基类的重载:

void /*B::*/func1(int) override
{
    A::func1("bla"s);
}

这将准确地调用基类的版本,虽然,不是的覆盖变体,但在给定的情况下,A 的变体是纯的virtual(即不存在),因此我们不能在这里应用这种方法。

【讨论】:

  • “使用 A::func1”正在工作。再次在 B 中声明抽象方法也是有效的。但是我收到 A::func1("bla"s) 的链接器错误。不适用于这个小例子。但在我的真实代码中。我认为这与一些函数是内联的而另一些不是的事实有关。
  • 我添加了一些关于链接器错误的信息。
  • @MartinFehrs 我的错:A::func1 是纯虚拟的,所以我们不能直接调用它...调整了答案。
【解决方案2】:

C 也有同样的问题 - 这将无法编译:

C c;
c.func1(123);

名称查找发生在重载决议之前,并且查找在找到第一个匹配项的范围内停止。

您可以使用using 将所有重载引入派生类的范围:

struct B : A
{
    using A::func1;  // Make the string overload available trough B's interface.
    void func1(int) override
    {
        func1("bla"s);
    }
};

struct C : B
{
    using B::func1; // Make the int overload available through C's interface.
    void func1(std::string) override
    {
    }
};

如果您调用 A::func1(std::string)并且为它提供了一个实现,您的代码也会编译;

struct A
{
    virtual void func1(int) = 0;
    virtual void func1(std::string) = 0;
};

// Yes, you can provide an implementation for a pure virtual function.
void A::func1(std::string) {}

struct B : A
{
    void func1(int) override
    {
        A::func1("bla"s);
    }
};

但是这段代码 - 你可能想要工作 - 不会:

void foo(B* b)
{
    b->func1("blargh"s);
}

【讨论】:

  • 我添加了一些关于链接器错误的信息。
  • @MartinFehrs 关于如何摆脱链接器错误,我也做了同样的事情。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-11
  • 2013-06-29
  • 2013-04-09
  • 2017-01-08
相关资源
最近更新 更多