什么是多态
接口有多种形态,能根据操作环境的不同采用不同的处理方式
编译时多态(静态绑定)
shape *ps;//静态类型shape*
shape *ps=new circle;//静态类型shape*
作用: 根据类型匹配等特征确定某一个同名函数到底是要调用哪一段函数
原理: 代码中声明的类型=对象的静态类型
通过: 函数重载/运算符重载
- 基类指针指向派生类,调用时仍然是基类函数
gstudent s2;//子类对象声明
ps=& s2;//!!基类指针可以指向派生类对象!!
ps->print();//因为未通过虚函数等动态绑定方法,所以此处为静态绑定(编译时多态)故编译器不知道派生类有重名函数,仍用基类函数
运算符重载
功能: 给已有运算符新的功能,使面对不同类型的数据有不同的行为(代替原来的函数功能)
实质: 函数重载
已预定义的运算符: 自动调用运算符函数operator+(i,j)
不能重载的运算符: “.” “*” “::” “?:”
重载方式:
- 类的非静态成员函数(有this指针)
-
() [] newdelete只能用此方式重载
- 友元函数(无this指针)
前置/后置运算符
clock& operator++();//前置,没有形参
相当于
a.operator++();
clock operator++(int);//后置,有形参
相当于
a.operator++(0);
-
后置运算符作类成员函数时 z+1->z.operator(1),1满足int 但1+z->1.operator(z),z不知是否满足->不支持交换律
对输出<<的重载
friend complex &operator<<(ostream& out, const complex& c);//输出<<友元重载,参数为os类的out对象
(省略)
ostream& operator<<(ostream& out, const complex& c) {
out << "(" << c.real << "," << c.imag << ")";//对输出格式的扩展
}
- 即代替了原来的display()函数
void complex::display()const {
cout << "(" << real << "+" << imag << "i)" << endl;//(a+bi)格式输出
}
(省略)
cout << "c1=";
c1.display();
对赋值=的重载
three_d & operator=(three_d & t);
three_d& three_d::operator=(three_d& t) {//3d类型的引用,用&,使*this有地址存放
x = t.x;
y = t.y;
z = t.z;
return *this;//与&对应,
}
- 只能是成员函数,不能友元
- 用于对已有对象改变其值,而复制构造函数用于创建一个新对象
运行时多态(动态绑定)
通过: 继承/虚函数
原理: 由运行时对象当前所指的对象类型决定,对象的动态类型表示它将执行何种行为。
shape *ps;//不指向任何对象,没有动态类型
shape *pc=new ciecle;//动态类型circle*
shape *pr=new rectangle;//动态类型rectangle*
改变动态类型:赋值
ps=pc;//ps的动态类型由无到circle*
虚函数
功能:
- 派生类可以重写基类中的虚函数,实现自己的功能
哪些不能做虚函数
- 非成员函数
- 构造函数
- 内联inline成员函数(∵编译时就被展开)
- 静态成员函数(本来就被所有对象共享)
- 友元函数(没有继承特性,就没有虚函数之说)
编译?运行?:
1、对象名.虚函数()->编译时多态
2、成员函数里调用虚函数->运行时多态
3、指针->虚函数->运行时多态
- 通过基类指针/引用调用才会动态绑定->各调用各自
-
因为基类指针可以指向派生类的对象,基类引用可以作为派生类对象的别名;反之不行
display在基类已声明为虚函数
void fun(base*ptr){//形参是指向基类的指针
ptr->display();//函数调用虚成员函数
}
base b;
derived d;
fun(&b);//基类display
fun(&d);//派生类display
- 通过派生类指针可以通过base::限定使输出总是基类display
void fun(derived* ptr) {//形参是指向派生类的指针,实参不能是基类对象
ptr->base::display();//加基类base限定,总会调用基类display
}
derived d;
fun(&d);//基类display
- 构造/析构函数调用虚函数: 只会调用派生类的虚函数
纯虚函数
是: 一个类中没有实现的函数,在派生类实现后 就不再是纯虚函数
用于: 基类不用声明具体功能,由各个派生类自己定义
声明:
virtual 函数类型 函数名(参数表)=0;//多了后面=0
对象切片
用派生类对象复制构造基类对象
derived d;//子类
base*ptr=&d;//
base&ref=d;
base b=d;//虽然是子类d赋值给b,但是调用的是base的复制构造函数