这三个关键字在cpp上经常碰到且很容易混淆,所以在这里记录他们的区别
##重载 (overload)
特征
- 在同一个类中
- 函数名相同
- 参数不同
- 与 virtual 关键字无关
例子
:::cpp
class foo{
public:
void printFoo(int x){cout<<x<<endl;}
void printFoo(float x){cout<<x<<endl;}
};
printFoo
名字相同但传入参数不同,这个情况就是重载了。
##覆盖 (override)
特征
- 在子类和父类之间
- 函数名相同
- 参数相同
- 父类函数必须有 virtual 修饰
例子
:::cpp
class father{
public:
virtual void printHello(void){ cout<<"i am father"<<endl;}
};
class son: public father{
public:
virtual void printHello(void){ cout<<"i am son"<<endl;}
};
覆盖是实现多态的重要特性。
##隐藏
特征
- 子类的函数名与父类相同,但参数不同,无论有没有 virtual 父类的方法都会被隐藏
- 子类的函数名与父类相同,参数相同,但是父类函数没有 virtual 关键字,父类的函数也会被隐藏。
函数如果被隐藏,其调用的方法不取决与实例,而取决于指向实例的指针。例如 有一个父亲的指针指向了其儿子的实例,当要调用这个指针的儿子方法的时候,其真正调用的是父方法,程序就达不到预期目的了。
例子
:::cpp
class father
{
public:
void printMethod(void);
};
void father::printMethod(void){
cout<<"father"<<endl;
}
:::cpp
class son: public father{
public:
void printMethod(void);
};
void son::printMethod(void){
cout<<"son"<<endl;
}
:::cpp
int main(int argc, char *argv[])
{
son tom;
father *jason = &tom;
tom.printMethod();
jason->printMethod();
return 0;
}
结果是
:::cpp
son
father
显然失去了多态的特性了。
cpp 的坑不少,一不小心就会掉进去了。尤其是指针,这可能就是 google 要为android 写 RefBase 的原因了。