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

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

  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.Second 例。
只需将第一个函数移动到基础 class:

#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;
}

程序输出
Derived::Write(wchar_t) 被调用
但我预计 "Base::Write(int) is called"
第二种情况有什么问题?

我猜这是因为程序找到了函数的 "newer" 版本,它与隐式转换是正确的,所以它没有寻找 "better" 函数来调用父 [=17] =]. 我建议: 1) 避免 overloading/redefining 具有可互换参数的函数。 2) 如果你真的想要 Derived::Write 被调用,使用 :

 p->Derived::Write(i);

你的编译器是对的。

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

您可以使用 using 将其导入派生的 class 作用域,使重载工作如您所愿。

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 class 范围内找到名为 Write 的成员函数,然后 name 查找 将停止,因此 Base 中的 Write 将永远不会被考虑用于 过载解决方案 ,即使基础 class 版本是在这里更合适。

Name lookup