一.多态性的概念
- 多态性是指一个名字,多种语义;或界面相同,多种实现。其中重载函数是多态性的一种简单形式。
- 虚函数允许函数调用与函数体的联系在运行时才进行,称为动态联编。
二.虚函数
- 标志:virtual
- 虚函数的作用就是实现多态性----以共同的方法,对不同的对象采取不同的策略。
- 定义:虚函数只能是类中的成员函数,而且不能是静态的。
- 语法:
class 类名
{
....virtual 返回类型 函数名(形式参数列表);//虚函数
}
- 注意,virtual只能在类内使用。不能将友元说明为虚函数,但虚函数可以是另一个类的友元。
- 析构函数可以是虚函数,但构造函数不能是虚函数。
- 当在派生类中相同的重载函数都保持虚特性。
- 在派生类中重载基类的虚函数要求函数名、返回类型、参数个数和参数类型和顺序完全相同。
- 如果仅仅返回类型不同,C++认为是错误重载;如果函数原型不同,仅函数名相同,丢失虚特性 。
- 使用虚函数并不一定产生多态,也不一定使用动态联编。例如,在调用中对虚函数成员使用成员名限定,可以强制C++对该函数的调用使用静态联编。
- 例子:
#include<iostream>
using namespace std;
class Point//表示平面上的点
{
private:
double x,y;//坐标值
public:
Point(double x1=0,double y1=0):x(x1),y(y1){}
virtual double area(){return 0;}//虚函数
};
class Circle:public Point//圆
{
double r;//半径
public:
Circle(double x,double y,double r1):Point(x,y),r(r1){}
virtual double area{return 3.14*r*r;}//虚函数
};
int main()
{
Point a(2.5,2.5);
Circle c(2.5,2.5,1);
Point *pc=&c;
cout<<"Circle area="<<pc->area()<<endl;//动态联编
cout<<"Circle area="<<pc->Point::area()<<endl;//静态联编
return 0;
}
- 虚函数实现多态的条件:
1.类之间的关系满足赋值兼容性规则;
2.改写了同名的虚函数;
3.根据赋值兼容性规则使用指针(或引用)。
注意:必须同时满足以上三条才能保证实现动态联编。
- 第三条分为两种情况:
1.使用基类指针或引用访问虚函数。例如:
Point *p=new Circle;//基类指针指向派生类
cout<<p->area();//动态联编
2.把指针或引用作为函数参数,这个函数不一定是类的成员函数,可以是普通函数,而且可以重载。例如:
void fun(Point *p)
{cout<<p->area();}//动态联编
- 在派生类中,当一个指向基类成员函数的指针指向一个虚函数,并且通过指向对象的基类指针或引用访问这个虚函数时,仍将发生多态性。
#include<iostream>
using namespace std;
class Base
{
public:
virtual void print{cout<<"Base"<<endl;}
};
class Derived:public Base
{
public:
void Print(){cout<<"Derived"<<endl;}
};
void display(Base *p,viod(Base::*pf)())
{
(p->*pf)();
}
int main()
{
Derived d;
Base b;
display(&d,&Base::print);
display(&b,&Base::print);
return 0;
}
- 析构函数可以是虚的。虚析构函数用于指引 delete 运算符正确析构动态对象 。
#include<iostream>
using namespace std ;
class A
{
public:
~A(){cout<<"A::~A() is called.\n";}
};
class B : public A
{
public:
~B(){cout<<"B::~B() is called.\n";}
};
int main()
{
A *Ap = new B;
B *Bp2 = new B;
cout<<"delete first object:\n";
delete Ap;
cout<<"delete second object:\n";
delete Bp2;
}
三.纯虚函数和抽象类
- 纯虚函数是一种特殊的虚函数。在许多情况下,在基类中不能对虚函数给出有意义的实现,而把它声明为纯虚函数,它的实
现留给该基类的派生类去做。
- 纯虚函数是一个在基类中说明的虚函数,在基类中没有定义, 要求任何派生类都定义自己的版本。
- 纯虚函数为各派生类提供一个公共界面。
- 纯虚函数说明形式:
virtual 类型 函数名(参数表)= 0 ;
- 一个具有纯虚函数的基类称为抽象类。
#include<iostream>
using namespace std;
class Sharp//抽象类
{
public:
virtual double area() =0;//纯虚函数
virtual double volumn() =0;//纯虚函数
};
class Circle:public Sharp//圆
{
public:
Circle(double a):r(a) {}
virtual double area(){return 2*3.1415926*r;}//虚函数
virtual double volumn(){return 0;}//虚函数
private:
double r;
};
class Cylinder:public Circle//圆柱体
{
public:
Cylinder(double a,double b):Circle(a),h(b) {}
virtual double volumn() {return area()*h;}//虚函数
private:
double h;
};
int main()
{
Circle a(10.0);
Cylinder b(5.6,10.5);
cout<<a.area()<<","<<b.volumn()<<endl;//静态联编
Sharp *pb;//定义基类指针
pb=&b;
pb=&b;
cout<<pb->area()<<","<<pb->volumn()<<endl;//动态联编
return 0;
}
小总结:
其实到现在我也还是没能很好地理解多态的使用方法,但是我知道它的作用还是很大的。比如系统一般都会有客户端和后台管理端,这就需要用多态实现不同的登录界面。所以学会多态还是很重要的。但是我对多态的理解就是用基类里面的虚函数向外扩展,实现同一个函数的不同功能实现。实际应用还是比较缺乏的。所以还是得加深理解。考完试了也知道自己什么水平了,还是好好学习吧。