用C ++重写基类的重载函数

可能重复:
C ++重载parsing

我遇到了一个问题,在我的课程覆盖了它的基类的一个函数之后,所有重载版本的函数都被隐藏了。 这是由devise还是我只是做错了什么?

防爆。

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); }; 

那么下面会给出一个编译错误,说bar中没有(double)函数。

 main() { double i = 0.0; bar b; ba(i); } 

在课堂栏中,添加

 using foo::a; 

这是C ++中常见的“陷阱”。 一旦在类作用域中find名称匹配,就不会在inheritance树上看到重载。 通过指定'using'声明,将'a'的所有重载从'foo'带入'bar'的范围。 然后超载正常工作。

请记住,如果存在使用“foo”类的现有代码,则其含义可能会因额外的重载而改变。 或者额外的重载可能会引入歧义,代码将无法编译。 詹姆斯·霍普金的回答指出了这一点。

这是语言用来工作的方式。 在使用关键字之前,如果您覆盖了一个重载函数,则必须全部重载:

 class bar : public foo { public: bar(void); ~bar(void); a(int); a(double d) { foo::a(d); } // add this } 

这让语言委员会加上了人们的使用function,但有些老习惯很难消除, 和habitués†有一个很好的论点。

正如詹姆斯·霍普金斯(James Hopkins)指出的,通过添加使用 ,程序员正在expression这样的意图:派生类将在没有任何警告的情况下,将任何未来的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; df(21); return 0; } 

输出将是“Derived :: Double!” 因为编译器会将整数参数提升为double。 g ++ 4.0.1 -Wall不会警告这个促销发生了。

取消注释(1)模拟未来更改为Base添加方法Base :: f(int)。 代码编译后,即使使用-Wall和“Derived :: Double!”也不会发出警告。 仍然是输出。

现在取消注释(2)模拟Derived程序员决定包含所有Base :: f签名的决定。 代码编译(没有警告),但是输出现在是“Base :: Int!”。

†我想不出一个英文单词“有养成习惯”,“沉迷”太强大。

这是devise。 重载parsing仅限于一个范围。 当附加函数被添加到基类或命名空间作用域时,它可以防止有效的代码改变意义的一些讨厌的情况。