为什么 c++ 编译器 (VS2013) 选择了错误的函数

Why c++ compiler (VS2013) chooses wrong function?

本文关键字:错误 函数 选择 c++ 编译器 VS2013 为什么      更新时间:2023-10-16
  1. 第一种情况

    #include <iostream>
    class A
    {
    public:
        virtual void Write(int i)
        {
            std::wcout << L"Write(int) is called" << std::endl;
        }
        virtual void Write(wchar_t c)
        {
            std::wcout << L"Write(wchar_t) is called" << std::endl;
        }
    };
    int _tmain(int argc, wchar_t* argv[])
    {
        A *p = new A();
        int i = 100;
        p->Write(i);
        return 0;
    }
    

完美工作。
程序输出
Write(int( 被调用

2.第二种情况。
只需将第一个函数移动到基类:

#include <iostream>
class Base
{
public:
   virtual void Write(int i)
   {
       std::wcout << L"Base::Write(int) is called" << std::endl;
   }
};
class Derived: public Base
{
public:
    virtual void Write(wchar_t c)
    {
        std::wcout << L"Derived::Write(wchar_t) is called" << std::endl;
    }
};
int _tmain(int argc, wchar_t* argv[])
{
    Derived *p = new Derived();
    int i = 100;
    p->Write(i);
    return 0;
}

程序输出
派生::写入(wchar_t( 被调用
但我期望"Base::Write(int(被调用">
第二种情况有什么问题?

你的编译器是对的。

在派生类中定义成员函数时,基类中同名的成员函数将被隐藏

您可以使用using将其导入派生类范围,使重载按预期工作。

class Derived: public Base
{
public:
    using Base::Write;
    virtual void Write(wchar_t c)
    {
        std::wcout << L"Derived::Write(wchar_t) is called" << std::endl;
    }
};

编辑

函数重载不会通过不同的范围。当您在 Derived 上调用 Write 时,将在Derived类范围中找到名为 Write 的成员函数,然后名称查找将停止,因此永远不会考虑重载解析Base中的Write,即使基类版本在这里更合适。

请参阅名称查找

我想这是因为程序找到了该函数的"较新"版本,该版本在隐式转换中是正确的,因此它不会寻找"更好"的函数在父类中调用。我建议:1( 避免使用可互换的参数重载/重新定义函数。2(如果你真的想调用Derived::Write,请使用:

 p->Derived::Write(i);