一.
#include <iostream>
using namespace std;
const double PI = 3.14;
class Shape
{
public:
Shape();
~Shape();
double calcArea();
};
class Circle:public Shape{
public:
Circle(double r);
~Circle();
double calcArea();
protected:
double m_dR;
};
class Rect:public Shape{
public:
Rect(double width,double height);
~Rect();
double calcArea();
protected:
double m_dWidth;
double m_dHeight;
};
Shape::Shape()
{
cout<<"Shape()"<<endl;
}
Shape::~Shape()
{
cout<<"~Shape()"<<endl;
}
double Shape::calcArea()
{
cout<<"Shape-->calcArea()"<<endl;
return 0;
}
Circle::Circle(double r)
{
cout<<"Circle()"<<endl;
m_dR = r;
}
Circle::~Circle(){
cout<<"~Circle()"<<endl;
}
double Circle::calcArea()
{
cout<<"Circle-->calcArea()"<<endl;
return PI*m_dR*m_dR;
}
Rect::Rect(double width,double height){
cout<<"Rect()"<<endl;
m_dHeight = height;
m_dWidth = width;
}
Rect::~Rect(){
cout<<"~Rect()"<<endl;
}
double Rect::calcArea()
{
cout<<"Rect-->clacArea()"<<endl;
return m_dHeight*m_dWidth;
}
int main()
{
Shape *shape1 = new Rect(3,6);
Shape *shape2 = new Circle(5);
shape1->calcArea();
shape2->calcArea();
delete shape1;
shape1 = NULL;
delete shape2;
shape2 = NULL;
return 0;
}
运行结果:
在父类的方法前加上virtual关键字后:
#include <iostream>
using namespace std;
const double PI = 3.14;
class Shape
{
public:
Shape();
~Shape();
virtual double calcArea();
};
class Circle:public Shape{
public:
Circle(double r);
~Circle();
double calcArea();
protected:
double m_dR;
};
class Rect:public Shape{
public:
Rect(double width,double height);
~Rect();
double calcArea();
protected:
double m_dWidth;
double m_dHeight;
};
Shape::Shape()
{
cout<<"Shape()"<<endl;
}
Shape::~Shape()
{
cout<<"~Shape()"<<endl;
}
double Shape::calcArea()
{
cout<<"Shape-->calcArea()"<<endl;
return 0;
}
Circle::Circle(double r)
{
cout<<"Circle()"<<endl;
m_dR = r;
}
Circle::~Circle(){
cout<<"~Circle()"<<endl;
}
double Circle::calcArea()
{
cout<<"Circle-->calcArea()"<<endl;
return PI*m_dR*m_dR;
}
Rect::Rect(double width,double height){
cout<<"Rect()"<<endl;
m_dHeight = height;
m_dWidth = width;
}
Rect::~Rect(){
cout<<"~Rect()"<<endl;
}
double Rect::calcArea()
{
cout<<"Rect-->clacArea()"<<endl;
return m_dHeight*m_dWidth;
}
int main()
{
Shape *shape1 = new Rect(3,6);
Shape *shape2 = new Circle(5);
shape1->calcArea();
shape2->calcArea();
delete shape1;
shape1 = NULL;
delete shape2;
shape2 = NULL;
return 0;
}
运行结果:
多态的语法核心是virtual关键字,必须使用virtual才能使多个类间建立多态关系。
二.
虚析构函数:防止内存泄漏
#include <iostream>
using namespace std;
const double PI = 3.14;
class Shape
{
public:
Shape();
virtual double calcArea();
virtual ~Shape();
};
class Coordinate
{
public:
Coordinate(int x, int y);
~Coordinate();
private:
int m_iX;
int m_iY;
};
Coordinate::Coordinate(int x, int y)
{
cout<<"Coordinate"<<endl;
m_iX = x;
m_iY = y;
}
Coordinate::~Coordinate()
{
cout<<"~Coordinate"<<endl;
}
class Rect:public Shape{
public:
Rect(double width,double height);
~Rect();
double calcArea();
protected:
double m_dWidth;
double m_dHeight;
};
class Circle:public Shape
{
public:
Circle(int x, int y, double r);
~Circle();
virtual double calcArea();
private:
double m_dR;
Coordinate *m_pCenter;
};
Shape::Shape()
{
cout<<"Shape()"<<endl;
}
Shape::~Shape()
{
cout<<"~Shape()"<<endl;
}
double Shape::calcArea()
{
cout<<"Shape-->calcArea()"<<endl;
return 0;
}
Circle::Circle(int x, int y, double r)
{
cout<<"Circle()"<<endl;
m_dR = r;
m_pCenter = new Coordinate(x,y);
}
Circle::~Circle(){
cout<<"~Circle()"<<endl;
delete m_pCenter;
m_pCenter = NULL;
}
double Circle::calcArea()
{
cout<<"Circle-->calcArea()"<<endl;
return PI*m_dR*m_dR;
}
Rect::Rect(double width,double height){
cout<<"Rect()"<<endl;
m_dHeight = height;
m_dWidth = width;
}
Rect::~Rect(){
cout<<"~Rect()"<<endl;
}
double Rect::calcArea()
{
cout<<"Rect-->clacArea()"<<endl;
return m_dHeight*m_dWidth;
}
int main()
{
Shape *shape1 = new Rect(3,6);
Shape *shape2 = new Circle(3,4,5.0);
shape1->calcArea();
shape2->calcArea();
delete shape1;
shape1 = NULL;
delete shape2;
shape2 = NULL;
return 0;
}
运行结果:
关于virtual的限制:
普通函数不能是虚函数,virtual只能修饰某个类的成员函数。
静态成员函数不能是虚函数,因为static函数是与类同生共死的,不依赖于对象。
内联函数不能是虚函数,如果修饰inline函数,计算机会忽略inline而把它变成虚函数。
构造函数不能为虚函数。
纯虚函数:
virtual double calaPerimeter() = 0;
含有纯虚函数的类叫作抽象类。
抽象类无法实例化对象。
接口类
仅含有纯虚函数的类称为接口类。
只有成员函数,而且成员函数都是纯虚函数。
RTTI:运行时类型识别
cout<<typeid(*obj).name()<<endl;
if(typeid(*obj)==typeid(Bird)){
Bird *Bird = dynamic_cast<Bird *>(obj);
}
dynamic_cast只能应用于指针和引用的转换
要转换的类型中必须包含虚函数
转换成功返回子类的地址,失败返回NULL。
typeid返回一个type_info对象的引用。只能获取对象的实际类型,而不能是指针的。
如果想通过基类的指针获得派生类的数据类型,基类必须带有虚函数。
异常处理
try…catch…尝试正常逻辑,捕获异常
throw… 抛出异常,让catch捕获处理