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函数调用。不是吗?如果我错了,请纠正我。你能发布程序的输出吗?