Brief
定义:同样的消息被不同类型的对象接收时产生不同的行为。
原理:1.编译时多态(静态绑定)
2.运行时多态(动态绑定)
分类:1.重载:包括函数重载,运算符重载 (静态绑定)
2.覆盖:包括子类和父类间虚函数、虚析构函数和纯虚函数 (动态绑定)
1. 重载
要求:1.函数名相同;2.参数不同
栗子:
#include <iostream>
using namespace std;
int add(int a, int b)
{
cout << "int_add_int_int" << endl;
return a + b;
}
int add(double a, double b)
{
cout << "int_add_double_double" << endl;
return a + b;
}
//报错:
//错误 2 error C2556: “double add(int,int)”: 重载函数与“int add(int,int)”只是在返回类型上不同
//错误 3 error C2371: “add”: 重定义;不同的基类型
//错误 4 error C2264: “add”: 函数定义或声明中有错误;未调用函数
//double add(int a, int b)
//{
// cout << "double_add_int_int" << endl;
// return a + b;
//}
int main()
{
add(1, 2);
add(1.0, 2.0);
system("pause");
return 0;
}
2.覆盖
要求:必须是虚函数的继承
有virtual:多态,调用函数只取决于参数指针所指向的地址,与指针没有关系(操作类型根据地址类型动态绑定)
没有virtual:不是多态,调用函数只取决于参数指针类型,与指向的地址无关1)一般虚函数继承
注:子类中与基类虚函数对应的函数可以不声明为虚函数,系统会自动判断子类中该函数是否为虚函数,判断标准为:
a.该函数是否与基类的虚函数有相同的名称
b.该函数是否与基类的虚函数有相同的参数个数及相同的对应参数类型
c.该函数是否与基类的虚函数有相同的返回值,或者满足赋值兼容规则的指针、引用型的返回值。
三条同时满足则判断为虚函数
栗子:
#include <iostream>
using namespace std;
class Base
{
public:
virtual void vprint()
{
cout << "v base" << endl;
}
void print()
{
cout << "base" << endl;
}
};
class Derived : public Base
{
public:
void vprint()
{
cout << "v derived" << endl;
}
void print()
{
cout << "derived" << endl;
}
};
int main()
{
Base b;
Derived d;
Derived* pd = (Derived*) &b;
Base* pb = (Base*) &d;
cout << "virtual call:" << endl;
pd->vprint();
pb->vprint();
cout << endl << "normal call:" << endl;
pd->print();
pb->print();
system("pause");
return 0;
}
2)虚析构函数
作用:基类的析构函数应定义为虚函数,否则,当用基类的指针调用子类的对象时调用的是基类的虚构函数,而子类中基类没有的部分没有被析构,造成内存泄露。
栗子:
#include <iostream>
using namespace std;
class Base
{
public:
~Base()
{
cout << "base destructed" << endl;
}
};
class Derived : public Base
{
public:
Derived()
{
p = new int(0);
}
~Derived()
{
cout << "derived destructed" << endl;
delete p;
}
private:
int* p;
};
int main()
{
Base* pb = new Derived();
Derived* pd = new Derived();
delete pb;
cout << endl;
delete pd;
system("pause");
return 0;
}
用Base* 调用的Derived类在析构的时候产生了内存泄露。如果将Base的析构函数改为虚函数,即
class Base
{
public:
virtual ~Base()
{
cout << "base destructed" << endl;
}
};
3)纯虚函数
作用:带有纯虚函数的类是抽象类,抽象类和纯虚函数都不能实现,只提供借口实现多态(抽象类不能实例化,但是可以做指针)
栗子:
#include <iostream>
using namespace std;
class Base
{
public:
virtual void print() = 0;
};
class Derived1 : public Base
{
public:
void print()
{
cout << "derived 1" << endl;
}
};
class Derived2 : public Base
{
public:
void print()
{
cout << "derived 2" << endl;
}
};
void fun(Base* p)
{
p->print();
}
int main()
{
//报错:
// 1 IntelliSense: 不允许使用抽象类类型 "Base" 的对象
//Base b;
Derived1 d1;
Derived2 d2;
fun(&d1);
fun(&d2);
system("pause");
return 0;
}