这就是语言过去的工作方式。在using关键字之前,如果您覆盖了一个重载函数,则必须将它们全部重载:
class bar : public foo
{
public:
bar(void);
~bar(void);
a(int);
a(double d) { foo::a(d); } // add this
}
这让很多人感到恼火,语言委员会增加了使用功能,但一些旧习惯很难改掉;和习惯者†有一个很好的论据。
正如詹姆斯霍普金斯指出的那样,通过添加using,程序员表达了派生类将在没有警告的情况下将任何未来的 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;
}
输出将是“Derived::Double!” 因为编译器会将整数参数提升为双精度。g++ 4.0.1 -Wall 不会警告此促销已发生。
取消注释 (1) 以模拟对 Base 添加方法 Base::f(int) 的未来更改。即使使用 -Wall 和“Derived::Double!”,代码也会再次编译,而不会发出警告。仍然是输出。
现在取消注释 (2) 以模拟 Derived 程序员决定包括所有 Base::f 签名。代码编译(没有警告),但输出现在是“Base::Int!”。
—
† 我想不出一个英语单词来形容“那些有习惯的人”和“上瘾的人”太强了。