Gre*_*reg 47 c++ polymorphism inheritance overriding
可能重复:
C++重载决议
我遇到了一个问题,在我的类重写了它的基类的函数后,所有重载的函数版本都被隐藏了.这是设计还是我做错了什么?
防爆.
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);
};
Run Code Online (Sandbox Code Playgroud)
然后,下面会给出一个编译错误,说明条中没有(双)函数.
main()
{
double i = 0.0;
bar b;
b.a(i);
}
Run Code Online (Sandbox Code Playgroud)
Fre*_*son 72
在课堂栏中,添加
using foo::a;
Run Code Online (Sandbox Code Playgroud)
这是C++中常见的"问题".一旦在类范围中找到名称匹配,它就不会进一步查看继承树的重载.通过指定'using'声明,您可以将'f'中的'a'的所有重载带入'bar'的范围.然后重载正常工作.
请记住,如果现有代码使用'foo'类,其含义可能会被其他重载更改.或者额外的重载可能会引入歧义,并且代码将无法编译.James Hopkin的回答指出了这一点.
Tho*_*day 21
这就是语言运作的方式.在使用using关键字之前,如果覆盖了一个重载函数,则必须将它们全部重载:
class bar : public foo
{
public:
bar(void);
~bar(void);
a(int);
a(double d) { foo::a(d); } // add this
}
Run Code Online (Sandbox Code Playgroud)
这使得语言委员会增加了使用功能的人很烦,但是一些旧的习惯很难; 和habitués†有一个很好的争论.
正如James Hopkins指出的那样,通过添加使用,程序员表达了这样的意图:派生类将在没有警告的情况下将foo :: a()的任何未来覆盖添加到其可接受签名列表中.
以下是他描述的一个例子:
#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;
}
Run Code Online (Sandbox Code Playgroud)
输出将是"Derived :: Double!" 因为编译器会将整数参数提升为double.g ++ 4.0.1 -Wall不会警告此促销活动已经发生.
取消注释(1)以模拟对Base添加方法Base :: f(int)的未来更改.即使使用-Wall,代码也会在没有任何警告的情况下编译,并且"Derived :: Double!" 仍然是输出.
现在取消注释(2)模拟Derived程序员决定包含所有Base :: f签名.代码编译(没有警告),但输出现在是"Base :: Int!".
-
†我想不出一个英文单词"有习惯的人"和"上瘾"太强了.