C++ 当返回类型和参数列表都更改时隐藏名称

C++ 当返回类型和参数列表都更改时隐藏名称,c++,name-hiding,C++,Name Hiding,我的基本问题是,当返回类型和参数列表都更改时,为什么名称隐藏不适用。请参考下面的样品 // Example program #include <iostream> #include <string> using namespace std; class base { public: int f() const { cout <<"I am base void version. "<<endl; return 1;} int f(s

我的基本问题是,当返回类型和参数列表都更改时,为什么名称隐藏不适用。请参考下面的样品

// Example program
#include <iostream>
#include <string>
using namespace std;

class base {
public:
    int f() const { cout <<"I am base void version. "<<endl; return 1;}
    int f(string) const { cout <<"I am base string version. "<<endl; return        1;}
};

class Derived1 : public base {
public:
    int f() const {
        cout << "Derived1::f()\n";
        return 2;
    }
};

class Derived2 : public base {
public:
    int f(int) const {
        cout << "Derived2::f()\n";
        return 3;
    }
};

class Derived3 : public base {
public:
    void f(int) const {
        cout << "Derived3::f()\n";
    }
};


int main()
{
    string s("hello");
    Derived1 d1;
    int x = d1.f();
 //d1.f(s); // string version hidden

   Derived2 d2;
   //x = d2.f(); // f() version hidden
    x = d2.f(1);

    Derived3 d3;
    d3.f(1); // No name hiding
 }
在上述程序中

a) 为什么Derived2对象的字符串版本不隐藏

b) 当返回类型和参数都匹配时,为什么名称隐藏不适用

“名称隐藏在编译器级别如何工作?”的任何链接或引用都很有用


谢谢。

来自比亚恩·斯特劳斯塔普自己的作品:

为什么重载对派生类不起作用? 该问题(在许多变体中)通常由以下示例引发:

#include<iostream>
using namespace std;

class B {
public:
  int f(int i) { cout << "f(int): "; return i+1; }
  // ...
};

class D : public B {
public:
  double f(double d) { cout << "f(double): "; return d+1.3; }
  // ...
};

int main()
{
  D* pd = new D;

  cout << pd->f(2) << '\n';
  cout << pd->f(2.3) << '\n';
}
而不是

  f(int): 3
  f(double): 3.6
一些人(错误地)猜到了

您可以修改问题中的程序,通过使用base::f添加
,使隐藏的重载可用到派生类:

#include <iostream>
#include <string>
using namespace std;

class base {
public:
    int f() const { cout <<"I am base int version. "<<endl; return 1; }
    int f(string) const { cout <<"I am base string version. "<<endl; return        1; }
};

class Derived1 : public base {
public:
    using base::f;
    int f() const
    {
        cout << "Derived1::f()\n";
        return 2;
    }
};

class Derived2 : public base {
public:
    using base::f;
    int f(int) const 
    {
        cout << "Derived2::f()\n";
        return 3;
    }
};

class Derived3 : public base {
public:

    void f(int) const
    {
        cout << "Derived3::f()\n";
    }
};


int main()
{
    string s("hello");
    Derived1 d1;
    int x = d1.f();
    d1.f(s); // string version hidden

    Derived2 d2;
    x = d2.f(); // f() version hidden
    x = d2.f(1);

    Derived3 d3;
    d3.f(1); // No name hiding
}

来自比亚恩·斯特劳斯塔普自己的作品:

为什么重载对派生类不起作用? 该问题(在许多变体中)通常由以下示例引发:

#include<iostream>
using namespace std;

class B {
public:
  int f(int i) { cout << "f(int): "; return i+1; }
  // ...
};

class D : public B {
public:
  double f(double d) { cout << "f(double): "; return d+1.3; }
  // ...
};

int main()
{
  D* pd = new D;

  cout << pd->f(2) << '\n';
  cout << pd->f(2.3) << '\n';
}
而不是

  f(int): 3
  f(double): 3.6
一些人(错误地)猜到了

您可以修改问题中的程序,通过使用base::f添加
,使隐藏的重载可用到派生类:

#include <iostream>
#include <string>
using namespace std;

class base {
public:
    int f() const { cout <<"I am base int version. "<<endl; return 1; }
    int f(string) const { cout <<"I am base string version. "<<endl; return        1; }
};

class Derived1 : public base {
public:
    using base::f;
    int f() const
    {
        cout << "Derived1::f()\n";
        return 2;
    }
};

class Derived2 : public base {
public:
    using base::f;
    int f(int) const 
    {
        cout << "Derived2::f()\n";
        return 3;
    }
};

class Derived3 : public base {
public:

    void f(int) const
    {
        cout << "Derived3::f()\n";
    }
};


int main()
{
    string s("hello");
    Derived1 d1;
    int x = d1.f();
    d1.f(s); // string version hidden

    Derived2 d2;
    x = d2.f(); // f() version hidden
    x = d2.f(1);

    Derived3 d3;
    d3.f(1); // No name hiding
}

名称隐藏 -若在派生类中给成员函数一个新的定义,则有两种可能性

  • 签名和返回类型保持不变

    ---函数重新定义(适用于普通成员函数)

    ---函数覆盖(用于虚拟成员函数)

  • 签名和返回类型更改 ---名称隐藏

    • 如果在派生类中为函数指定了新定义,则所有其他版本将自动隐藏在派生类中

    • 不能跨作用域重载


  • 名称隐藏 -若在派生类中给成员函数一个新的定义,则有两种可能性

  • 签名和返回类型保持不变

    ---函数重新定义(适用于普通成员函数)

    ---函数覆盖(用于虚拟成员函数)

  • 签名和返回类型更改 ---名称隐藏

    • 如果在派生类中为函数指定了新定义,则所有其他版本将自动隐藏在派生类中

    • 不能跨作用域重载


  • 字符串
    重载隐藏在
    Derived2
    中。你不能调用
    d2.f(s)
    。当我运行这个程序时,输出是
    Derived1::f()Derived2::f()Derived3::f()
    ,所以我们在每种情况下都隐藏了名称?问题的a)部分和b)部分对我来说都没有意义。是的@flatmouse。如果存在名称隐藏,理想情况下应该限制derived3函数调用,对吗?由于编译器在基类中发现名称匹配,它将停止调用derived3版本。如果我错了,请纠正我。是的,巴里。我不明白为什么以及如何阻止字符串调用而不是void函数。基本上,编译器应该匹配一个名称来应用名称隐藏,所以它应该在第一次找到void函数时阻止void函数调用。不是吗?如果我错了,请纠正我。你能发布程序的输出吗?
    字符串
    重载隐藏在
    Derived2
    中。你不能调用
    d2.f(s)
    。当我运行这个程序时,输出是
    Derived1::f()Derived2::f()Derived3::f()
    ,所以我们在每种情况下都隐藏了名称?问题的a)部分和b)部分对我来说都没有意义。是的@flatmouse。如果存在名称隐藏,理想情况下应该限制derived3函数调用,对吗?由于编译器在基类中发现名称匹配,它将停止调用derived3版本。如果我错了,请纠正我。是的,巴里。我不明白为什么以及如何阻止字符串调用而不是void函数。基本上,编译器应该匹配一个名称来应用名称隐藏,所以它应该在第一次找到void函数时阻止void函数调用。不是吗?如果我错了,请纠正我。你能发布程序的输出吗?