重载:
分为两种:
- 函数重载:C++允许在同一作用域中声明几个类似的同名函数,这些同名函数的形参列表(参数个数,类型,顺序)必须不同,常用来处理实现功能类似数据类型不同的问题。
- 运算符重载:使用户自定义的数据以更简洁的方式工作
函数重载的规则:
- 函数名必须相同
- 参数列表必须不同(个数不同、类型不同、参数排列顺序不同等)
- 函数返回类型可以相同,可以不同
- 仅仅返回类型不同不足以成为函数的重载
- 作用域相同
例子:
class A
{
public:
void test(int i);
void test(double i);
void test(int i, double j);
void test(double i, int j);
int test(int i);
};
解释:前四个函数互为重载函数,后四个也互为重载函数,第一个与第五个不是重载函数
函数重载的作用:
重载函数用来在同一个作用域内用同一个函数名命名一组功能相似的函数,这样做减少了函数名的数量,避免了名字空间的污染,对于程序的可读性有很大的好处。
函数重载是一种静态多态
多态:用同一个东西表示不同的形态;
多态分为:
- 静态多态(编译时的多态);
- 动态多态(运行时的多态);
重写(覆盖): 派生类覆盖基类函数
重写翻译自override,也翻译成覆盖(更好一点),是指派生类中存在重新定义的函数。其函数名,参数列表,返回值类型,所有都必须同基类中被重写的函数一致。只有函数体不同(花括号内),派生类调用时会调用派生类的重写函数,不会调用被重写函数。重写的基类中被重写的函数必须有virtual修饰。
重写的规则:
- 不同的范围(分别位于派生类与基类);
- 函数名字相同;
- 参数相同;
- 基类函数必须有 virtual 关键字,不能有 static ;
- 返回值相同(或是协变),否则报错;
- 重写函数的访问修饰符可以不同。尽管 virtual 是 private 的,派生类中重写改写为 public,protected 也是可以的;
例子:
#include<iostream>
using namespace std;
class A
{
public:
virtual void fun3(int i)
{
cout << "A::fun3() : " << i << endl;
}
};
class B : public A
{
public:
//重写类A中的fun3()
virtual void fun3(int i)
{
cout << "B::fun3(): " << i << endl;
}
};
int main()
{
A a;
B b;
A * pa = &a;
pa->fun3(3);
pa= &b;
pa->fun3(5);
system("pause");
return 0;
}
运行结果:
隐藏(重定义):派生类的函数屏蔽了与其同名的基类函数。
注意只要同名函数,不管参数列表是否相同,基类函数都会被隐藏。
例子:
#include<iostream>
using namespace std;
class A
{
public:
virtual void fun3(int i,int j)
{
cout << "A::fun3() : " << i<<" "<<j << endl;
}
};
class B : public A
{
public:
//重写类A中的fun3()
virtual void fun3(double i)
{
cout << "B::fun3(): " << i << endl;
}
};
int main()
{
B b;
b.fun3(5);
//b.fun3(1, 2);隐藏了基类的同名函数,所以不能运行
system("pause");
return 0;
}
重载和重写的区别:
(1)范围区别:重写和被重写的函数在不同的类中,重载和被重载的函数在同一类中。
(2)参数区别:重写与被重写的函数参数列表一定相同,重载和被重载的函数参数列表一定不同。
(3)virtual的区别:重写的基类必须要有virtual修饰,重载函数和被重载函数可以被virtual修饰,也可以没有。
隐藏和重写,重载的区别:
(1)与重载范围不同:隐藏函数和被隐藏函数在不同类中。
(2)参数的区别:隐藏函数和被隐藏函数参数列表可以相同,也可以不同,但函数名一定同;当参数不同时,无论基类中的函数是否被virtual修饰,基类函数都是被隐藏,而不是被重写。