多态
1 概念
面向对象系统的多态性是指不同的对象收到相同的的消息时, 执行不同的操作
编译时的多态性
多态性
运行时的多态性
编译时多态性主要是通过函数重载和运算符重载实现的。
运行时多态性主要是通过虚函数来实现的。
注
在C++中规定: 基类的对象指针可以指向它的公有派生的对象,但是当其指向公有派生类对象时,
它只能访问派生类中从基类继承来的成员,而不能访问公有派生类中定义的成员
例如
#include<iostream.h> //例6.1-1 虚函数引例
class base {
int a,b;
public:
base(int x,int y) { a=x; b=y; }
void show( )
{ cout<<"调用基类base的show函数\n";
cout<<"a=" <<a<<“b="<<b<<endl; } };
class dirive:public base {
int c;
public:
dirive(int x,int y,int z):base(x,y){c=z;}
void show( ) { cout<< "调用派生类dirive的show函数\n";
cout<<"c="<<c<<endl; } };
void main( )
{ base mb(50,50), *mp; dirive mc(10,20,30);
mp=&mb; mp->show( );
mp=&mc; mp->show( ); }
运行结果是
调用基类base的show函数
a=50 b=50
调用基类base的show函数
a=10 b=20
2 虚函数
1)虚函数的作用和定义
1.虚函数的作用
虚函数就是在基类中被关键字virtual说明,并在派生类中重新定义的函数
例如
#include<iostream.h> //例5.2-1
class base {
int a,b;
public:
base(int x,int y) { a=x; b=y; }
virtual void show( ) {cout<<"调用基类base的show函数\n";//
在基类中,show()定义为虚函数
cout<<"a=" <<a<<"b="<<b<<endl; } };
class dirive: public base {
int c;
public: dirive(int x,int y,int z):base(x,y){ c=z; }
void show( ) { cout<< "调用派生类dirive的show函数\n"; cout<<"c="<<c<<endl; }
};//
在派生类中,重新定义虚函数show()
void main( )
{ base mb(50,50), *mp;
dirive mc(10,20,30);//
调用基类base的show()函数
mp=&mb; mp->show(); //
mp=&mc; mp->show()//
调用派生类dirive的show()函数
;}
3虚析构函数
#include<iostream> //例6.6-1 虚析构函数的使用。
using namespace std;
class B{
public:
virtual ~B()
{ cout<<"调用基类B的析构函数\n";}
};
class D:public B{
public:
~D()
{ cout<<"调用派生类D的析构函数\n";}
};
int main()
{ B *p; //定义指向基类B的指针变量p
p= new D;
delete p;
return 0; }
1 将基类的析构函数声明为虚析构函数
2 使用了虚析构函数, 程序执行了动态联编,实现了运行的多态性
(1) 虚析构函数没有类型,也没有参数。
(2) 如果将基类的析构函数定义为虚函数,由该基类所派生的所有派生类的析构函数也都自动成为虚函数。
(3)在C++中,不能声明虚构造函数,但是可以声明虚析构函数。
4 纯虚函数和抽象类
1 基类本身并不需要这个虚函数,而是为派生类提供一个公共接口,以便派生类根据需要重新定义虚函数
2
纯虚函数的特点:
① 纯虚函数没有函数体;
② 最后面的“=0”并不表示函数的返回值为0,它只起形式上的作用,告诉编译系统“这是纯虚函数”;
③ 纯虚函数不具备函数的功能,不能被调用
例子:
#include<iostream.h>
class Circle {
protected:
int r;
public:
void setr(int x){ r=x; }
virtual void show( )=0;
};
class Area:public Circle{
public:
void show( )
{ cout<<"这个圆的面积是:"<<3.14*r*r<<endl;} };
class Perimeter:public Circle{
public:
void show( )
{ cout<<"这个圆的周长是: "<<2*3.14*r<<endl;} };
void main( )
{ Circle *ptr;
Area ob1;
Perimeter ob2;
ob1.setr(10);
ob2.setr(10);
ptr=&ob1; ptr->show();
ptr=&ob2; ptr->show(); }
5 抽象类
1 作用 抽象类的作用是作为一个类族的共同基类,相关的派生类是从这个基类派生出来的
2 使用抽象类的几点规定
(1) 由于抽象类中至少包含有一个没有定义功能的纯虚函数,
因此抽象类只能用作其他类的基类,不能建立抽象类对象。
(2) 不允许从具体类派生出抽象类。所谓具体类,就是不包含纯虚函数的普通类;
(3) 抽象类不能用作函数的参数类型、函数的返回类型或显式转换的类型;
(4) 可以声明指向抽象类的指针或引用,此指针可以指向它的派生类,进而实现多态性。
(5) 在派生类中,如果对基类的纯虚函数没有重新定义,则该函数在派生类中仍是纯虚函数,该派生类仍为抽象类。
例如:
#include<iostream>
using namespace std;
class Figure{
protected:
double r;
public:
Figure(double x){ r=x; }
virtual void area()=0; //纯虚函数
virtual void perimeter()=0; //纯虚函数
};
class Circle:public Figure{
public:
Circle(double x):Figure(x){ }
void area()
{ cout<<"圆的面积是"<<3.14*r*r<<endl; }
void perimeter( )
{ cout<<"圆的周长是";
cout<<2*3.14*r<<endl; }
};
class In_square:public Figure{
public:
In_square(double x):Figure(x){ }
void area()
{ cout<<" 圆内接正方形的面积是";
cout<<2*r*r<<endl;}
void perimeter( )
{ cout<<"圆内接正方形的周长是";
cout<<4*1.414*r<<endl; }
};
class Ex_square:public Figure{
public:
Ex_square(double x):Figure(x){ }
void area()
{ cout<<" 圆外切正方形的面积是";
cout<<4*r*r<<endl;}
void perimeter( )
{ cout<<"圆外切正方形的周长是";
cout<<8*r <<endl; }
};
int main()
{
Figure *ptr; //定义抽象类Figure的指针ptr
Circle ob1(5); //定义类Circle的对象ob1
In_square ob2(5); //定义类In_square的对象ob2
Ex_square ob3(5); //定义类Ex_square的对象ob3
ptr=&ob1; ptr->area(); //求圆的面积
ptr->perimeter(); //求圆的周长
ptr=&ob2; ptr->area(); //求圆内接正方形的面积
ptr->perimeter(); //求圆内接正方形的周长
ptr=&ob3; ptr->area(); //求圆外切正方形的面积
ptr->perimeter(); //求圆外切正方形的周长
return 0; }