【问题标题】:C++ inline base class method must be explicitly resolved?C++内联基类方法必须显式解析?
【发布时间】:2014-02-24 20:57:30
【问题描述】:

我的类层次结构中的继承和方法解析有一个奇怪的问题。代码正在使用带有-O0 的clang++ 5.0 编译。我有两个这样的课程:

class PrintBase
{
protected:
    static wstring_convert<codecvt_utf8<wchar_t>> sConverter;

public:
    virtual void PrintChar(wchar_t ch) = 0;
    inline  void PrintChar(char ch)
    {
        PrintChar(sConverter.from_bytes(ch)[0]);
    }

    virtual void PrintString(const wstring& str) = 0;
    inline  void PrintString(const string& str)
    {
        PrintString(sConverter.from_bytes(str));
    }
};

class Print: public PrintBase
{
public:
    virtual void PrintChar(wchar_t ch) override;
    virtual void PrintString(const wstring& str) override;
};

void Print::PrintChar(wchar_t ch)
{
    // do stuff
}

void Print::PrintString(const wstring& str)
{
    // do stuff
}

如果我构造一个 Print 实例 Print* pnt = new Print(); 并调用 pnt-&gt;PrintChar('c');,它会正确调用内联基类方法,进行转换,然后正确调用派生类中实现的虚拟覆盖。

如果我调用 pnt-&gt;PrintString("test");pnt-&gt;PrintString(string("test"));pnt-&gt;PrintString(someString); 我会收到错误消息:

No viable conversion from 'basic_string<char, char_traits<char>, allocator<char>>' to 'const basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t>>'

...在“from”类型的常量上有一些变化。拨打pnt-&gt;PrintString(L"test"); 或类似电话将按预期工作。我可以强制它使用pnt-&gt;PrintBase::PrintString("test");调用内联字符串&函数

为什么它能够正确解析和调用基类中的内联char方法,但在没有显式解析作用域的情况下无法对string&方法这样做?

【问题讨论】:

  • 我不小心提前提交了问题,编辑刚刚因站点维护而停机!如果您在我有机会完成问题之前偶然发现此问题,请稍后再回来查看。

标签: c++ inheritance c++11 clang inline


【解决方案1】:

您所拥有的设置是覆盖函数的经典示例隐藏其他继承的重载。

当一个函数在派生类中被重写时,该重写函数会隐藏基类的所有其他重载。重载解析是在选择名称之后进行的,因此一旦确定PrintString 引用Print::PrintString,它就永远不会考虑PrintBase::PrintString,即使前者不接受提供的参数而后者会。

最直接的方法是使用using 声明将继承但未覆盖的名称引入派生类:

class Print: public PrintBase
{
public:
    virtual void PrintChar(wchar_t ch) override;
    using PrintBase::PrintChar;

    virtual void PrintString(const wstring& str) override;
    using PrintBase::PrintString;
};

我不相信通过Print 对象调用PrintChar('x') 实际上会调用内联重载。它真正要做的是从您传入的char 初始化wchar_t。它是否可能与您的情况下的内联版本做同样的事情?

【讨论】:

  • 是的,using 指令运行良好。我没有意识到这将是一个问题,因为通常任何具有相同名称的被覆盖的东西都将是虚拟的。不过,关于 char/wchar_t 转换,我在调试器中确认它正在调用内联函数。我可以介入,看它调用转换函数,然后将结果转发给虚函数。很奇怪。
  • @BrighamToskin 请注意,即使其他重载为 virtual,这也适用,但并非所有重载都被覆盖。
  • @BrighamToskin 关于char 过载:这很奇怪。这两个调用都是通过相同的(静态)对象类型发生的吗?
  • 是的,我分配了一个 Print 对象,分配给了一个 Print*。如果我添加一个带有断点和单步执行的调用 pnt-&gt;PrintChar('c');,我会点击内联代码。
猜你喜欢
  • 2022-11-18
  • 2020-09-02
  • 2023-03-18
  • 2012-08-13
  • 2019-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多