在 C++ 中覆盖 Base 的重载函数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/888235/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Overriding a Base's Overloaded Function in C++
提问by Greg
Possible Duplicate:
C++ overload resolution
可能的重复:
C++ 重载解析
I ran into a problem where after my class overrode a function of its base class, all of the overloaded versions of the functions were then hidden. Is this by design or am I just doing something wrong?
我遇到了一个问题,在我的类覆盖其基类的函数后,所有重载的函数版本都被隐藏了。这是设计使然还是我做错了什么?
Ex.
前任。
class foo
{
public:
foo(void);
~foo(void);
virtual void a(int);
virtual void a(double);
};
class bar : public foo
{
public:
bar(void);
~bar(void);
void a(int);
};
the following would then give a compile error saying there is no a(double) function in bar.
下面会给出一个编译错误,说 bar 中没有 a(double) 函数。
main()
{
double i = 0.0;
bar b;
b.a(i);
}
回答by Fred Larson
In class bar, add
在类栏中,添加
using foo::a;
This is a common 'gotcha' in C++. Once a name match is found in the a class scope, it doesn't look further up the inheritance tree for overloads. By specifying the 'using' declaration, you bring all of the overloads of 'a' from 'foo' into the scope of 'bar'. Then overloading works properly.
这是 C++ 中常见的“陷阱”。一旦在 a 类作用域中找到名称匹配,它就不会进一步查找继承树的重载。通过指定 'using' 声明,您将 'a' 的所有重载从 'foo' 带入了 'bar' 的作用域。然后重载正常工作。
Keep in mind that if there is existing code using the 'foo' class, its meaning could be changed by the additional overloads. Or the additional overloads could introduce ambiguity and and the code will fail to compile. This is pointed out in James Hopkin's answer.
请记住,如果存在使用 'foo' 类的现有代码,其含义可能会因额外的重载而改变。或者额外的重载可能会引入歧义,并且代码将无法编译。詹姆斯霍普金的回答中指出了这一点。
回答by Thomas L Holaday
That is the way the language used to work. Prior to the usingkeyword, if you overrode one overloaded function, you had to overload them all:
这就是该语言过去的工作方式。在using关键字之前,如果您覆盖了一个重载函数,则必须将它们全部重载:
class bar : public foo
{
public:
bar(void);
~bar(void);
a(int);
a(double d) { foo::a(d); } // add this
}
This annoyed enough people that the language committee added the usingfeature, but some old habits die hard; and the habitués† have a good argument.
这惹恼了很多人,语言委员会添加了使用功能,但一些旧习惯很难改掉;和惯习者† 有一个很好的论据。
As James Hopkins points out, by adding using, the programmer is expressing the intention that the derived class will, without warning, add any future overrides of foo::a() to its list of acceptable signatures.
正如 James Hopkins 指出的那样,通过添加using,程序员表达了派生类将在没有警告的情况下将 foo::a() 的任何未来覆盖添加到其可接受签名列表中的意图。
Here is an example of what he describes:
这是他描述的一个例子:
#include <iostream>
class Base {
public:
virtual void f(double){ std::cout << "Base::Double!" << std::endl; }
// virtual void f(int) { std::cout << "Base::Int!" << std::endl; } // (1)
virtual ~Base() {}
};
class Derived : public Base {
public:
// using Base::f; // (2)
void f(double) { std::cout << "Derived::Double!" << std::endl; }
};
int main(int, char **) {
Derived d;
d.f(21);
return 0;
}
The output will be "Derived::Double!" because the compiler will promote the integer argument to a double. g++ 4.0.1 -Wall will not warn that this promotion occurred.
输出将是“Derived::Double!” 因为编译器会将整数参数提升为双精度值。g++ 4.0.1 -Wall 不会警告此促销已发生。
Uncomment (1) to simulate a future change to Base adding the method Base::f(int). The code compiles, again without warning even with -Wall, and "Derived::Double!" remains the output.
取消注释 (1) 以模拟对 Base 的未来更改,添加方法 Base::f(int)。即使使用 -Wall 和“Derived::Double!”,代码也会编译,再次没有警告。仍然是输出。
Now uncomment (2) to simulate a decision by the Derived programmer to include all Base::f signatures. The code compiles (without warnings), but the output is now "Base::Int!".
现在取消注释 (2) 以模拟派生程序员决定包括所有 Base::f 签名。代码编译(没有警告),但输出现在是“Base::Int!”。
—
—
† I cannot think of an English word for "those who have the habit" and "addicted" is much too strong.
† 我想不出一个英文词来形容“有习惯的人”和“上瘾的人”太强烈了。
回答by James Hopkin
It is by design. Overload resolution is restricted to a single scope. It prevents some nasty cases of valid code changing meaning when additional functions are added to a base class or to namespace scope.
这是设计使然。重载解析仅限于单个作用域。当额外的函数被添加到基类或命名空间作用域时,它可以防止一些令人讨厌的有效代码改变含义的情况。