和其他函数一样,类的成员函数不论是否是虚函数都可以被重载(重载的发生需要是在同一作用域)。然而,派生类一旦声明了一个和基类重载函数同名的函数,派生类将会覆盖基类的所有重载函数,也就是说派生类可以覆盖基类重载函数的0个或全部个实例。
如下代码:
class Base
{
public:
void func() { printf("Base func()\n"); };
void func(int a) { printf("Base func(int a)\n");}
};
class D1 : public Base
{
public:
void func(string& str) { printf("D1 func(string& str)\n"); }
};
int main(void)
{
D1 d1;
d1.func(); //报错,基类的func()函数已被隐藏
d1.func(2); //报错,基类的func(int)函数已被隐藏
return 0;
}
显然,派生类D1的func(string& str)函数把基类Base中所有名为”func”的函数都隐藏了,要想通过D1调用func()和func(int)函数,要么在D1类中重新定义函数,要么使用using关键字将Base类中所有”func”成员包含到派生类中:
class D1 : public Base
{
public:
using Base::func; //将基类的func所有重载实例到包含到D1中
void func(string& str) { printf("D1 func(string& str)\n"); }
};
int main(void)
{
D1 d1;
d1.func();
d1.func(2);
return 0;
}
在D1中加上”using Base::func;”后编译通过。
using声明语句指定一个名字而不指定形参列表,所以一条基类成员函数的using声明语句就可以将函数的所有重载实例添加到派生类作用域中。此时,派生类只需要定义自身特有的函数,不需要为继承而来的其他函数重新定义。这样,外界对派生类没有重新定义的重载函数的访问实际上是对using声明点的访问。
需要注意的是,using关键字还能改变基类的该成员函数在派生类中的访问级别:
class Base
{
protected:
void func() { printf("Base func()\n"); }
void func(int a) { printf("Base func(int a)\n");}
};
class D1 : public Base
{
public:
using Base::func; //将原本是protected属性改为public
void func(string& str) { printf("D1 func(string& str)\n"); }
};
int main(void)
{
D1 d1;
d1.func();
d1.func(2);
return 0;
}
编译运行: