学习c++过程中,我们必须对重载、隐藏和重写的特性进行了解并且对他们进行区分。那么我们首先来了解重载的概念。在相同作用域中,当有几个函数名相同,参数不同的函数我们称为重载。例如下面的代码:
class Base {
public:
Base();
virtual ~Base();
void fun(int);
void fun(string);
};
Base::Base() {
// TODO Auto-generated constructor stub
}
void Base::fun(int i){
cout<<"fun(int i)"<<endl;
}
void Base::fun(string str){
cout<<"fun(string str)"<<endl;
}
Base::~Base() {
// TODO Auto-generated destructor stub
}
int main(){
Base b;
b.fun(1);
b.fun("hello world");
return 0;
}
Base类里有两个fun函数,但他们的参数不同,这就是重载。当你调用fun函数时传递int类型的参数,就会调用fun(int)函数,但传递string类型参数就会调用fun(string)这个函数,这也是c++多态的一种表现。当执行main函数会打印fun(int i)和fun(string str),这个结果就证明了你调用相同名字的成员函数,根据传递的参数类型调用相应的成员函数。
重载得注意三点:
1.不能根据成员函数的返回值不同进行重载。如果有int fun(int)和void fun(int)这两个函数,如果你int i = fun(1),那么我们是知道调用int fun(int),但在c++中返回值是可以被忽略的,也就是说你执行fun(1)这样一条语句,编译器无法去编译区分你要调用哪个函数。
2.全局函数和类成员函数同名,参数不同,这不叫重载,因为作用域不一样。
3.注意隐式转换带来的隐患。比如int fun(int)和int fun(float)这两个函数,当你fun(0.5)这样子调用它时,这个时候就会产生二义性,它不知道你是想转换成int型还是float型,自然也就不知道调用哪个函数了。这个我用代码测试过,编译都通不过的。
说完重载接下来就说隐藏,什么是隐藏?当派生类中的成员函数(成员变量)名和基类中的成员函数(成员变量)名相同时,会隐藏基类的成员函数(成员变量),也就是指在派生类调用这个同名的成员函数(成员变量),调用的是派生类的成员函数(成员变量),而不是基类的那个成员函数(成员变量)。那么我们该怎么去访问基类的同名成员函数(成员变量)呢?可以通过类名::成员函数(成员变量)这样子去访问同名的成员函数。代码如下:
class Base {
public:
Base();
virtual ~Base();
void fun(int);
int x;
};
Base::Base() {
// TODO Auto-generated constructor stub
}
void Base::fun(int i){
cout<<"Base::fun(int i)"<<endl;
}
Base::~Base() {
// TODO Auto-generated destructor stub
}
class Derived: public Base {
public:
Derived();
virtual ~Derived();
void fun();
string x;
};
Derived::Derived() {
// TODO Auto-generated constructor stub
}
void Derived::fun(){
cout<<"Derived::fun()"<<endl;
}
Derived::~Derived() {
// TODO Auto-generated destructor stub
}
int main(){
Base b;
Derived d;
d.x = "hello";
// d.x = 1234; 错
cout<<"x="<<d.x<<endl;
d.Base::x = 1234;
d.fun();
// d.fun(1);错
d.Base::fun(1);
return 0;
}
通过观察上面的代码,Derived继承Base类,但Derived成员变量string x却与Base类中的int x名字相同,所以直接访问x的话访问的是Derived里string x而不是从Base类继承下来的int x,这就是上面所说的隐藏。main函数中d.x = 1234这条语句虽然编译没错,但是运行过程中打印d.x的值却是个问号。同理,成员函数fun()和从Base类继承下来的fun(int)是同名的,所以直接访问fun(1)是会编译出错的。要访问从基类继承下来的同名成员函数,需通过类名::成员变量(成员函数)这样子去使用。
说完了隐藏再来说重写,其实隐藏搞懂了,重写很好理解,因为重写就是隐藏规则里的一种。只是重写的表现是当你在派生类中写的成员函数与基类的成员函数重名,并且参数个数和类型一致,就称为重写。当你直接访问成员函数调用的是你在派生类中重写的函数而不是从基类继承下来的成员函数,如果要访问从基类继承下来的成员函数也是通过类名::成员函数这种方式去调用基类的成员函数。所以才说重写是隐藏规则里的一种。重写也是表现C++多态的一种形式,重写可以把对象继承下来的需要修改的函数进行改写,保留不需要改写的函数,有了这种机制,我们就不需要从零开始重新写一个类,使得继承才有意义。