【问题标题】:Why c++ compiler (VS2013) chooses wrong function?为什么 c++ 编译器(VS2013)选择了错误的函数?
【发布时间】:2016-02-13 14:54:10
【问题描述】:
  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;
}

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

【问题讨论】:

  • @hvd:我认为这是重复的,但不是that question
  • @hvd:这个问题确实通过派生类型的指针进行查找,即通过基类型。这个问题介绍了不同范围内的功能,一个在基类中介绍了它们。另一个问题似乎只是关于虚拟调度如何调用最衍生的覆盖器,与隐藏无关。
  • @hvd:或者另一个问题将“坏”(有趣)行为放在首位。在这种情况下,这个问题实际上调用了派生类中的重载,该问题调用了基类中的重载。名称隐藏在另一个问题中根本没有作用。
  • @BenVoigt 这已经足够令人信服了,谢谢。快速搜索会找到 C++ inheritance and name hidingC++ inheritance, base methods hidden 尽可能更好的重复候选人。

标签: c++ inheritance member-functions name-lookup name-hiding


【解决方案1】:

你的编译器是对的。

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

您可以使用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 的成员函数,然后名称查找 将停止,因此@ 中的Write 987654329@ 永远不会被考虑用于重载解决,即使基类版本在这里更合适。

Name lookup

【讨论】:

  • 但是函数有不同的参数类型。为什么 Write(wchar_t) 隐藏了 Write(int)?对吗?
  • @Alex 请查看我编辑的答案。这是正确的行为。
  • 感谢您的详细解释。
【解决方案2】:

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

 p->Derived::Write(i);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 2015-01-05
    • 2020-01-30
    相关资源
    最近更新 更多