重写:调用子类
隐藏:调用父类
重载
特点:
-
相同的作用域内
-
参数列表不同(参数的类型,个数,顺序不同)
-
函数名字相同;函数返回类型相同
例如:
class A{
public:
void test(int i);
void test(double i);//overload
void test(int i, double j);//overload
void test(double i, int j);//overload
int test(int i); //错误,非重载。注意重载不关心函数返回类型。
};
重载原理:
C++代码在编译时会根据函数名+参数列表
进行重命名,以此区分不同的函数从而实现重载的(c语言只根据函数名所以无法实现重载)
例如:
void Swap(int a, int b)会被重命名为_Swap_int_int
void Swap(float x, float y)会被重命名为_Swap_float_float
当发生函数调用时,编译器会根据传入的实参去逐个匹配,以选择对应的函数,如果匹配失败,编译器就会报错,这叫做重载决议
如果参数类型使用const进行修饰,那么函数是否能重载成功呢?
当使用const修饰函数参数时,函数重载是否生效取决于是顶层const还是底层const
- 顶层const无法重载
因为顶层const是指变量本身不可变即常量,可以绑定到普通变量上,所以对于编译器来说无法区分两个函数,不知道用户是要调用那个函数 - 编译器可以区分底层const,所以可以实现重载
重写
特点:
-
不在同一个作用域(分别位于派生类与基类) ;
-
基类函数必须有 virtual 关键字,不能有 static 。
-
函数名字相同;参数相同;返回值相同
-
函数体不同
java的特点:
两同两小一大原则:
两同:方法名和参数列表相同
两小:返回值或声明异常比父类小(或相同)
一大:访问修饰符比父类的大(或相同)
举例:
#include<iostream>
using namespace std;
class Base
{
public:
virtual void fun(int i){ cout << "Base::fun(int) : " << i << endl;}
};
class Derived : public Base
{
public:
virtual void fun(int i){ cout << "Derived::fun(int) : " << i << endl;}
};
int main()
{
Base b;
Base * pb = new Derived();
pb->fun(3);//Derived::fun(int)
system("pause");
return 0;
}
隐藏
是指派生类的函数屏蔽了与其同名的基类函数,注意只要求同名,不管参数列表是否相同,基类函数都会被隐藏。
和重写的区别:
重写必须满足:基类和派生类的参数列表相同,且基类函数有virtual关键字修饰
隐藏是:同名且不满足重写即为隐藏
隐藏的特点:
(1)不在同一个作用域(分别位于派生类与基类) ;
(2)函数名字相同;
(3)参数、返回值、函数体都可以不同;
举例:
#include <iostream>
using namespace std;
class Base
{
public:
void fun(double ,int ){ cout << "Base::fun(double ,int )" << endl; }
};
class Derive : public Base
{
public:
void fun(int ){ cout << "Derive::fun(int )" << endl; }
};
int main()
{
Derive pd;
pd.fun(1);//Derive::fun(int )
pb.fun(0.01, 1);//error 基类的fun被隐藏了
system("pause");
return 0;
}