一:多态概念
指相同对象收到不同消息或者不同对象收到相同消息时产生不同的动作。
多态又分为:静态多态(早绑定)和动态多态(晚绑定)
二:虚函数及其原理
/**********************************************************************************************/
动态多态、虚函数
要求:
1.定义Shape类,成员函数:calcArea();构造函数,析构函数
2.定义Rect类,成员函数:calcArea(),构造函数,析构函数
数据成员:m_dWidth(),m_dHeight
3.定义Circle类,成员函数:calcArea(),构造函数,析构函数
数据成员:m_dR
/**********************************************************************************************/
代码如下:
/*Shape.h*/
#ifndef SHAPE_H
#define SHAPE_H
#include<iostream>
using namespace std;
class Shape
{
public:
Shape();
~Shape();
double calcArea();
};
#endif // !SHAPE_H
/*Shape.cpp*/
#include"Shape.h"
Shape::Shape()
{
cout << "Shape()" << endl;
}
Shape::~Shape()
{
cout << "~Shape()" << endl;
}
double Shape::calcArea()
{
cout << "Shape->calcArea()" << endl;
return 0;
}
/*Circle.h*/
#ifndef CIRCLE_H
#define CIRCLE_H
#include"Shape.h"
class Cirlce:public Shape
{
public:
Cirlce(double r);
~Cirlce();
double calcArea();
protected:
double m_dR;
};
#endif
/*Circle.cpp*/
#include"Circle.h"
Cirlce::Cirlce(double r)
{
cout << "Circle()" << endl;
m_dR = r;
}
Cirlce::~Cirlce()
{
cout << "~Cirlce()" << endl;
}
double Cirlce::calcArea()
{
cout << "Cirlce->calcArea()" << endl;
return 3.14*m_dR*m_dR;
}
/*Rect.h*/
#ifndef RECT_H
#define RECT_H
#include"Shape.h"
class Rect:public Shape
{
public:
Rect(double width,double height);
~Rect();
double calcArea();
protected:
double m_dWidth;
double m_dHeight;
};
#endif
/*Rect.cpp*/
#include"Rect.h"
Rect::Rect(double width, double height)
{
m_dWidth = width;
m_dHeight = height;
cout << "Rect()" << endl;
}
Rect::~Rect()
{
cout << "~Rect()" << endl;
}
double Rect::calcArea()
{
cout << "Rect->calcArea()" << endl;
return m_dHeight*m_dWidth;
}
/*demo.cpp*/
#include<iostream>
#include<stdlib.h>
#include"Circle.h"
#include"Rect.h"
using namespace std;
int main(void)
{
Shape *shape1 = new Rect(3,4);
Shape *shape2 = new Cirlce(5);
shape1->calcArea();
shape2->calcArea();
delete shape1;
shape1 = NULL;
delete shape2;
shape2 = NULL;
system("pause");
return 0;
}
首先是创建Rect对象,创建子类Rect对象时先创建父类对象Shape,同理,创建子类Circle对象时先创建父类对象Shape。然后发现shap1->calcArea()和shape2->calcArea()都调用的是父类的方法,并不是我们想要的结果。那么这就用到了虚函数,关键字为:Virtual
代码修改如下:
class Shape
{
public:
Shape();
~Shape();
virtual double calcArea();
};
class Cirlce:public Shape
{
public:
Cirlce(double r);
~Cirlce();
virtual double calcArea();
protected:
double m_dR;
};
class Rect:public Shape
{
public:
Rect(double width,double height);
~Rect();
virtual double calcArea();
protected:
double m_dWidth;
double m_dHeight;
};
运行结果如下:
什么情况下不能使用virtual:
1.virtual不能修饰普通函数
2.virtual不能修饰静态成员函数
3.virtual不能修饰内联函数
4.virtual不能修饰构造函数
3.虚析构函数
/**********************************************************************************************/
虚析构函数
要求:
1.定义Shape类,成员函数:calcArea();构造函数,析构函数
2.定义Rect类,成员函数:calcArea(),构造函数,析构函数
数据成员:m_dWidth(),m_dHeight
3.定义Circle类,成员函数:calcArea(),构造函数,析构函数
数据成员:m_dR
4.定义Coordinate类,成员函数:构造函数、析构函数
数据成员:m_iX,m_iY
/**********************************************************************************************/
代码改动如下:/*Coordinate.h*/
class Coordinate
{
public:
Coordinate(int x,int y);
~Coordinate();
private:
int m_iX;
int m_iY;
};
/*Coordiante.cpp*/
#include<iostream>
#include"Coordinate.h"
using namespace std;
Coordinate::Coordinate(int x,int y)
{
cout << "Coordinate()" << endl;
m_iX = x;
m_iY = y;
}
Coordinate::~Coordinate()
{
cout << "~Coordinate()" << endl;
}
/*Circle.h*/
#ifndef CIRCLE_H
#define CIRCLE_H
#include"Shape.h"
#include"Coordinate.h"
class Cirlce:public Shape
{
public:
Cirlce(double r);
~Cirlce();
virtual double calcArea();
protected:
double m_dR;
Coordinate *m_pCenter;
};
#endif
/*Shape.h*/
#ifndef SHAPE_H
#define SHAPE_H
#include<iostream>
using namespace std;
class Shape
{
public:
Shape();
virtual~Shape();
virtual double calcArea();
};
#endif // !SHAPE_H
/*Circle.cpp*/
#include"Circle.h"
Cirlce::Cirlce(double r)
{
cout << "Circle()" << endl;
m_dR = r;
m_pCenter = new Coordinate(3,5);//在子类中申请内存
}
Cirlce::~Cirlce() //子类析构函数释放内存
{
delete m_pCenter;
m_pCenter = NULL;
cout << "~Cirlce()" << endl;
}
double Cirlce::calcArea()
{
cout << "Cirlce->calcArea()" << endl;
return 3.14*m_dR*m_dR;
}
因为在这个例子中用到了指针,要释放掉Cricle子类申请的内存,为了避免使用父类对象释放子类指针造成内存泄露,父类Shape中必须使用虚析构函数。
运行结果如下: