纯虚函数的声明:
virtual 函数类型 函数名 (参数表列) = 0;
class Person
{
virtual void Display () = 0; // 纯虚函数
protected :
string _name ; // 姓名
};
class Student : public Person
{};
纯虚函数的特点:
- 纯虚函数具备函数的名字,但没有函数体,不能被调用
- 纯虚函数的作用是在基类中为其派生类保留一个函数的名字,以便派生类根据需要对他进行定义。
- 如果在一个类中声明了纯虚函数,在其派生类中没有对其函数进行定义,则该虚函数在派生类中仍然为纯虚函数。
抽象类(接口类):
- 不能创建对象而只作为一种基本类型用作继承的类叫做抽象类(也叫接口类)
- 凡是包含纯虚函数的类都是抽象类
- 抽象类的作用是作为一个类族的共同基类,为一个类族提供公共接口
- 抽象类不能实例化出对象
虚函数和纯虚函数:
- 如果在类外定义虚函数,只能在声明函数时加virtual关键字,定义时不用加。
- 不要在构造函数和析构函数中调用虚函数,在构造函数和析构函数中,对象是不完整的,可能会出现未定义的行为。
- 最好将基类的析构函数声明为虚函数。(析构函数比较特殊,因为派生类的析构函数跟基类的析构函数名称不一样,但是构成覆盖,这里编译器做了特殊处理)
- 只有类的非静态成员函数才能定义为虚函数,静态成员函数不能定义为虚函数。被static修饰的函数在编译时候要求前期bind,然而虚函数却是动态绑定(run-time bind),而且被两者修饰的函数生命周期(life recycle)也不一样。
- 多态性指相同对象收到不同消息或不同对象收到相同消息时产生不同的实现动作。C++支持两种多态性:编译时多态性,运行时多态性。
a.编译时多态性:通过重载函数实现
b 运行时多态性:通过虚函数实现。
虚函数和抽象基类的应用:
静态关联和动态关联
#include <iostream>
using namespace std;
//声明抽象基类Shape
class Shape
{
public:
virtual float area()const //虚函数
{
return 0.0;
}
virtual void shapeName()const = 0;//纯虚函数
//shapeNamea函数的作用是输出具体的形状,在派生类中定义,因此声明为纯虚函数
};
//声明Point类
class Point:public Shape
{
public:
Point(float a = 0.0, float b = 0.0)
{
x = a;
y = b;
}
void setPoint(float a, float b)
{
x = a;
y = b;
}
float getX()const
{
return x;
}
float getY()const
{
return y;
}
virtual void shapeName()const
{
cout<<"Point:";
}
friend ostream & operator <<(ostream &_cout, const Point &p)//【友元函数,操作符重载】
{
_cout<<"["<<p.x<<","<<p.y<<"]";
return _cout;
}
protected:
float x;
float y;
};
//声明Ciircle类
class Circle:public Point
{
public:
Circle(float a = 0.0, float b = 0.0, float r = 0.0):Point(a, b),radius(r){}
void setRadius(float r)
{
radius = r;
}
float getRadius()const
{
return radius;
}
virtual float area()const
{
return 3.1415926*radius*radius;
}
virtual void shapeName()const
{
cout<<"Circle:";
}
friend ostream & operator <<(ostream &_cout, const Circle &c)
{
_cout<<"["<<c.x<<","<<c.y<<"],r="<<c.radius;
return _cout;
}
protected:
float radius;
};
int main()
{
Point point(3.2, 4.5); // 建立Point类对象point
Circle circle(2.4, 1.2, 5.6); //建立Circle类对象circle
point.shapeName(); //静态关联
cout<<point<<endl;
circle.shapeName(); //静态关联
cout<<circle<<endl;
Shape* pt; //定义基类指针
pt = &point;
pt->shapeName();
cout<<"x="<<point.getX()<<",y="<<point.getY()<<endl;
cout<<"area="<<pt->area()<<endl;
pt = &circle; //指针指向Circle类对象
pt->shapeName(); //动态关联
cout<<"x="<<circle.getX()<<",y="<<circle.getY()<<endl;
cout<<"area="<<pt->area()<<endl;
system("pause");
return 0;
}
运行结果:
结论:
- 一个基类如果包含一个及以上纯虚函数,就是抽象基类。
- 抽象基类不能也没必要定义对象。
- 在类的层次结构中,顶层或最上面几层可以是抽象基类。抽象基类体现了本类族中各类的共性,把各类中共有的成员函数集中在抽象基类中声明。
- 抽象基类是本类族的共公共接口,即就是从同一基类中派生出的多个类有同一接口。