纯虚函数
1.虚函数是实现多态性的前提
1.1需要在基类中定义共同的接口
1.2接口要定义为虚函数
2.如果基类的接口没办法实现怎么办?
如形状类Shape
3解决办法
将这些接口定义为纯虚函数
抽象类
1.在基类中不能给出有意义的虚函数定义,这时可以把它说明成纯虚函数,把它的定义留给派生类来做
2.定义纯虚函数:
class 类名{
virtual 返回值类型 函数名(参数表) = 0;
};
3.纯虚函数不需实现。
4.作用
4.1抽象类为抽象和设计的目的而声明,将有关的数据和行为组织在一个继承层次结构中,保证派生类具有要求的行为。
4.2对于暂时无法实现的函数,可以声明为纯虚函数,留给派生类去实现。
5.注意:
抽象类只能作为基类来使用。
不能声明抽象类的对象
构造函数不能是虚函数,析构函数可以是虚函数。
6.抽象类不能用于直接创建对象实例,可以声明抽象类的引用和指针。
7.可使用指向抽象类的指针支持运行时多态。
8.派生类中必须实现基类中的纯虚函数,否则它仍将被看作一个抽象类。
class Shape
{
public:
virtual ~Shape() {}
virtual void Draw() = 0;
};
class Circle : public Shape
{
public:
void Draw() {
cout << "Circle::Draw()..." << endl; }
};
class Square : public Shape
{
public:
void Draw() {
cout << "Square::Draw()..." << endl; }
};
void DrawAllShape(const vector<Shape*>& v)
{
vector<Shape*>::const_iterator it;
for (it = v.begin(); it != v.end(); ++it) {
(*it)->Draw(); }
}
int main()
{
//Shape s; // Error,抽象类不能实例化对象
vector<Shape*> v;
Shape* ps;
ps = new Circle; v.push_back(ps);
ps = new Square; v.push_back(ps);
DrawAllShape(v);
}
运行结果:
演示第5条
class Shape
{
public:
virtual ~Shape() {} // xxxxxx
virtual void Draw() = 0;
};
class Circle : public Shape
{
public:
void Draw() {
cout << "Circle::Draw()..." << endl; }
~Circle() { cout << "~Circle..." << endl; }
};
class Square : public Shape
{
public:
void Draw() {
cout << "Square::Draw()..." << endl; }
~Square() { cout << "~Square..." << endl; }
};
void DrawAllShape(const vector<Shape*>& v)
{
vector<Shape*>::const_iterator it;
for (it = v.begin(); it != v.end(); ++it) {
(*it)->Draw(); }
}
void DeleteAllShape(const vector<Shape*>& v)
{
vector<Shape*>::const_iterator it;
for (it = v.begin(); it != v.end(); ++it) {
delete(*it); } // 必须将抽象类的析构函数为虚函数
}
int main()
{
//Shape s; // Error,抽象类不能实例化对象
vector<Shape*> v;
Shape* ps;
ps = new Circle;
v.push_back(ps);
ps = new Square;
v.push_back(ps);
DrawAllShape(v);
DrawAllShape(v);
}
main函数里重复,随后引出简单工厂模式,以及动态创建技术。
多态
1.多态性有助于更好地对程序进行抽象
1.1 控制模块能更专注一般性问题的处理
1.2 具体的操作交给具体的对象去做
2.多态性有助于提高程序的可扩展性
2.1 可以把控制模块与被操作的对象分开
2.2 可以添加自己定义的类的新对象,并能管理该对象
2.3 可以添加新类(已有类的派生类)的新对象,并能管理该对象
虚析构函数
1.析构函数可以声明为纯虚函数
1.1 delete基类指针
1.2 程序会根据基类指针指向的对象的类型确定要调用的析构函数
1.3 基类的析构函数为虚函数,所有派生类的析构函数都是虚函数
2.构造函数不得是虚函数
3.如果要操作具有继承关系的类的动态对象,最好使用虚析构函数。特别是在析构函数需要完成一些有意义的操作------比如释放内存时
4.析构函数还可以是纯虚的。