我的类层次结构中的继承和方法解析存在一个奇怪的问题。该代码使用clang ++ 5.0和-O0
进行编译。我有两个类,如:
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->PrintChar('c');
它正确调用内联基类方法,进行转换,然后在派生类中正确调用已实现的虚拟覆盖。
如果我致电pnt->PrintString("test");
或pnt->PrintString(string("test"));
或pnt->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->PrintString(L"test");
之类的内容可以像预期的那样工作。我可以强制它调用内联字符串&amp;函数pnt->PrintBase::PrintString("test");
为什么它能够正确地解析并调用基类中的内联char方法,但是对于字符串&amp;而言却无法这样做。没有明确解析范围的方法?
答案 0 :(得分:5)
您拥有的设置是覆盖隐藏其他继承重载的重写函数的典型示例。
在派生类中重写函数时,该重写函数会隐藏基类中的所有其他重载。选择名称后会出现重载决策,因此一旦确定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;
};
我不相信通过PrintChar('x')
对象调用Print
实际上会调用内联重载。它真正做的是从你传入的wchar_t
初始化char
。它是否可能与你的情况下的内联版本做同样的事情?