多态
多态的实现
- 绑定是指将一个标识符名和一个存储地址联系在一起的过程
- 编译时的多态,绑定工作在编译连接阶段完成的情况称为静态绑定
- 运行时的多态,绑定工作在程序运行阶段完成的情况称为动态绑定
一.虚函数和抽象类
用virtual关键字说明的函数
- • 虚函数是实现运行时多态性基础
- • C++中的虚函数是动态绑定的函数
- • 虚函数必须是非静态的成员函数
- • 虚函数经过派生之后,就可以实现运行过程中的多态
纯虚函数声明格式
//在基类声明,要求各派生类重写
virtual 函数类型 函数名(参数表) = 0;
抽象类
• 定义:抽象类是带有纯虚函数的类。对于暂时无法实现的函数,可以声明为纯虚函数,留给派生类去实现。
• 作用:通过多态性调用虚函数。
• 注意:
- ▫ 抽象类只能作为基类来使用。
- ▫ 不能声明抽象类的对象。
- ▫ 构造函数不能是虚函数,析构函数可以是虚函数
一道例题
#include <iostream>
using namespace std;
class Shape{//抽象类
public:
virtual double area() const =0;//纯虚函数
};
class Circle:public Shape{
public:
Circle(double r):radius(r){}
virtual double area() const {return 3.1415926*radius*radius;};
protected:
double radius;
};
class Square:public Shape{
public:
Square(double s):side(s){}
virtual double area() const {return side*side;}
protected:
double side;
};
class Rectangle:public Shape{
public:
Rectangle(double w,double h):width(w),height(h){}
virtual double area() const {return width*height;}
protected:
double width,height;
};
class Trapezoid:public Shape{
public:
Trapezoid(double t,double b,double h):top(t),bottom(t),height(h){}
virtual double area() const {return 0.5*(top+bottom)*height;}
protected:
double top,bottom,height;
};
class Triangle:public Shape{
public:
Triangle(double w,double h):width(w),height(h){}
virtual double area() const {return 0.5*width*height;}
protected:
double width,height;
};
int main(){
double r,zside,jwith,jheight,tbottom,ttop,theight,sbottom,sheight;
cin>>r>>zside>>jwith>>jheight>>tbottom>>ttop>>theight>>sbottom>>sheight;
Circle circle(r);
Square square(zside);
Rectangle rectangle(jwith,jheight);
Trapezoid trapezoid(tbottom,tbottom,theight);
Triangle triangle(sbottom,sheight);
Shape *pt[5]={&circle,&square,&rectangle,&trapezoid,&triangle};//基类指针数组
double areas=0.0;
for(int i=0;i<5;i++)
areas=areas+pt[i]->area();
cout<<"total of all areas = "<<areas<<endl;
return 0;
}
二.运算符重载(实质为函数重载)
1.规则和限制
- 可以重载C++中除下列运算符外的所有运算符:. .* :: ?:
- 只能重载C++中已有的运算符,不可臆造新的
- 不改变原运算符的优先级和结合性
- 不能改变操作数个数
- 经重载的运算符,其操作数中至少应该有一个是自定义类型
2.两种形式
声明形式
函数类型 operator 运算符(形参)
{
......
}
- 重载为类的成员函数
复数加减
#include <iostream>
using namespace std;
class Complex {
public:
Complex(double r = 0.0, double i = 0.0)
{real=r;imag=i; }
Complex operator + (Complex &c2) ;
Complex operator - (Complex &c2);
void display() const;
private:
double real; //复数实部
double imag; //复数虚部
};
Complex Complex::operator + (Complex &c2){
//创建一个临时无名对象作为返回值
return Complex(real+c2.real,imag+c2.imag);
}
Complex Complex::operator - (Complex &c2){
return Complex(real - c2.real, imag - c2.imag);
}
void Complex::display() const {
cout << "(" << real << ", " << imag << ")" << endl;
}
int main() {
Complex c1(5, 4), c2(2, 10), c3;
cout << "c1 = "; c1.display();
cout << "c2 = "; c2.display();
c3 = c1 - c2; //使用重载运算符完成复数减法
cout << "c3 = c1 - c2 = "; c3.display();
c3 = c1 + c2;//使用重载运算符完成复数加法
cout << "c3 = c1 + c2 = "; c3.display();
return 0;
}
- 重载为非成员函数(通常设置为友元函数)
负数加减
#include <iostream>
using namespace std;
class Complex { //复数类定义
public: //外部接口
Complex(double r = 0.0, double i = 0.0) :
real(r), imag(i) { } //构造函数
friend Complex operator + (Complex &c1,Complex &c2); //友元函数(运算符+重载)
friend Complex operator - (Complex &c1,Complex &c2); //运算符-重载
friend ostream & operator << (ostream &out1, Complex &c); //运算符<<重载
private: //私有数据成员
double real; //复数实部
double imag; //复数虚部
};
Complex operator + (Complex &c1, Complex &c2) {
return Complex(c1.real + c2.real, c1.imag+c2.imag);
}
Complex operator - (Complex &c1, Complex &c2) {
return Complex(c1.real - c2.real, c1.imag - c2.imag);
}
ostream & operator <<(ostream &out1, Complex &c){
out1 << "(" << c.real << ", " << c.imag << ")";//输出流
return out1;
}
int main() {
Complex c1(5, 4), c2(2, 10), c3;
cout << "c1 = "<<c1;
cout << "c2 = "<<c2;
c3 = c1 - c2;
cout << "c3 = c1 - c2 = "<<c3;
c3 = c1 + c2;
cout << "c3 = c1 + c2 = "<<c3;
return 0;
}