多态
多态分为两种,分别为静态多态,动态多态
- 静态多态:函数重载与运算符重载
- 动态多态:虚函数与不同子类继承重写对应函数实现运行时的多态
- 两者的区别:
静态多态在编译阶段就确定多态的函数地址
动态多态在运行阶段确定多态的函数地址
静态多态举例:
//日期类
class date
{
public:
date();
date(int year, int month, int day);
//这里重载了构造函数,(同名函数,作用域相同,参数列表不同),属于典型的静态多态
void set(int year, int month, int day);
void showdate();
~date();
private:
int m_year;
int m_month;
int m_day;
};
- 多态现在一般的用法,就是拿一个父类的指针去调用多个子类中被重写的方法。定义是在程序运行时根据基类对象的指针引用来确定具体要调用的类的虚函数,也就是多数会特意用的都是下面要说的动态多态。
- 就是所谓的一个接口,多种实现,——————举个例子,笔记本电脑的USB接口,可以插U盘,插鼠标接线,插键盘接线,这个USB接口就是父类定义的方法,另外的多种实现就是子类定义的同名函数,这里说的是实现时的情况,
- 下面讲实现需要的步骤与要注意的点。
- 在父类的函数前加上virtual关键字定义,目的是让父类的函数与子类的同名函数联系起来,这就是类的多态性,实现动态的绑定。
- 虚函数的定义,要满足的重写的前提。相同函数名,相同参数,参数类型,返回值,出现一个不一样就不可以。
- 只有类里面的成员函数可以定义为虚函数,类外的普通函数不可以。
- 构造函数不可以定义为虚函数,因为构造的时候,类对象还是未定型的空间,构造完成后,对象才是具体类的实例。
- 析构函数可以定义为虚函数,并且通常定义为虚函数。
这里引出一个纯虚函数的定义
在成员函数(必须为虚函数)的形参列表后面写上=0,则成员函数为纯虚函数。包含纯虚函数的类叫做抽象类(也叫接口类),抽象类不能实例化出对象。纯虚函数在派生类中重新定义以后,派生类才能实例化出对象。纯虚函数是一定要被继承的,否则它存在没有任何意义。
看例子:
//加入了对长方体,立方体,球体,圆柱及三棱柱的体积与表面积计算
#include "iostream"
#include "cmath"
using namespace std;
class line //线
{
public:
line(float len);
virtual float area() = 0;
//这里的在已经是虚函数的后面加上了‘=0’,成为了纯虚函数,所以这个线类成为了抽象类,不能够实例化对象。
//另外,声明为虚函数之后,继承此类的子类再定义该函数的时候,就不会在出现函数指向的二义性问题了。
virtual float volume() = 0;
protected:
float m_len;
};
line::line(float len) : m_len(len)
{
}
class rec : public line //矩形
{
public:
rec(float len, float width);
float area();
protected:
float m_width;
};
rec::rec(float len, float width) : line(len), m_width(width)
{
}
float rec::area()
{
return m_len * m_width;
}
class cuboid : public rec //长方体
{
public:
cuboid(float len, float width, float height);
float area();
float volume();
protected:
float m_height;
};
cuboid::cuboid(float len, float width, float height) : rec(len, width), m_height(height)
{
}
float cuboid::area()
{
return 2 * (m_len * m_width + m_len * m_height + m_height * m_width);
}
float cuboid::volume()
{
return m_len * m_height * m_width;
}
class cube : public cuboid //立方体
{
public:
cube(float len);
};
cube::cube(float len) : cuboid(len, len, len)
{
}
class cir : public line //圆
{
public:
cir(float len);
float area();
};
cir::cir(float len) : line(len)
{
}
float cir::area()
{
float q = acos(-1);
return m_len * m_len * q;
}
class glo : public cir //球体
{
public:
glo(float len);
float area();
float volume();
};
glo::glo(float len) : cir(len)
{
}
float glo::area()
{
float q = acos(-1);
return 4 * m_len * m_len * q;
}
float glo::volume()
{
float q = acos(-1);
return 4 * q * m_len * m_len * m_len / 3;
}
class cyl : public cir //圆柱
{
public:
cyl(float len, float height);
float area();
float volume();
protected:
float m_height;
};
cyl::cyl(float len, float height) : cir(len), m_height(height)
{
}
float cyl::area()
{
float q = acos(-1);
return m_len * m_len * q * 2 + 2 * q * m_len * m_height;
}
float cyl::volume()
{
float q = acos(-1);
return m_len * m_len * q * m_height;
}
class cone : public cir //圆锥
{
public:
cone(float len, float height);
float area();
float volume();
protected:
float m_height;
};
cone::cone(float len, float height) : cir(len), m_height(height)
{
}
float cone::area()
{
float q = acos(-1);
float l = sqrt(m_len * m_len + m_height * m_height);
return m_len * m_len * q + q * l * m_len;
}
float cone::volume()
{
float q = acos(-1);
return m_len * m_len * q * m_height / 3;
}
class tri : public line //三角形
{
public:
tri(float len, float len2, float len3);
float area();
protected:
float m_len2;
float m_len3;
};
tri::tri(float len, float len2, float len3) : line(len), m_len2(len2), m_len3(len3)
{
}
float tri::area()
{
float q = (m_len + m_len2 + m_len3) * (m_len + m_len2 - m_len3) * (m_len - m_len2 + m_len3) * (-m_len + m_len2 + m_len3);
return sqrt(q) / 4;
}
class tria : public tri //直三棱柱
{
public:
tria(float len, float len2, float len3, float height);
float area();
float volume();
protected:
float m_height;
};
tria::tria(float len, float len2, float len3, float height) : tri(len, len2, len3), m_height(height)
{
}
float tria::area()
{
float q = (m_len + m_len2 + m_len3) * (m_len + m_len2 - m_len3) * (m_len - m_len2 + m_len3) * (-m_len + m_len2 + m_len3);
return sqrt(q) / 2 + (m_len + m_len2 + m_len3) * m_height;
}
float tria::volume()
{
float q = (m_len + m_len2 + m_len3) * (m_len + m_len2 - m_len3) * (m_len - m_len2 + m_len3) * (-m_len + m_len2 + m_len3);
return sqrt(q) * m_height / 4;
}
int main()
{
//这里用父类对象指向子类对象的函数调用,是典型动态多态的使用
//也就是“一个接口,多种实现”。
line *p = new cuboid(10, 20, 30);
cout << "长方体表面积: " << p->area() << endl;
cout << "长方体体积: " << p->volume() << endl;
cout << endl;
delete p;
p = new cube(15);
cout << "正方体表面积: " << p->area() << endl;
cout << "正方体体积: " << p->volume() << endl;
cout << endl;
delete p;
p = new glo(10);
cout << "球表面积: " << p->area() << endl;
cout << "球体积: " << p->volume() << endl;
cout << endl;
delete p;
p = new cyl(10, 10);
cout << "圆柱表面积: " << p->area() << endl;
cout << "圆柱体积: " << p->volume() << endl;
cout << endl;
delete p;
p = new cone(10, 10);
cout << "圆锥表面积: " << p->area() << endl;
cout << "圆锥体积: " << p->volume() << endl;
cout << endl;
delete p;
p = new tria(3, 4, 5, 100);
cout << "三棱柱表面积: " << p->area() << endl;
cout << "三棱柱体积: " << p->volume() << endl;
cout << endl;
delete p;
return 0;
}