Version3.0多态第九章2回顾继承访问控制继承中的构造函数和析构函数函数覆盖3目标虚函数纯虚函数抽象类动态绑定虚析构函数4虚函数基类的指针可以指向派生类的对象但调用的函数却是基类的函数虚函数可以解决这个问题5示例2-1#includeiostream.hclassShapes{public:voiddraw()//基类中的函数{cout绘制基本形状\n;}};classCircle:publicShapes{private:intradius;public:voiddraw()//在派生类中重新定义{cout绘制圆形\n;}};6示例2-2classSquare:publicShapes{private:intlength;public:voiddraw()//在派生类中重新定义{cout绘制正方形\n;}};voidmain(){Circlec;Squares;Shapes*ptr;ptr=&c;ptr-draw();ptr=&s;ptr-draw();}调用Shapes的draw()方法7虚函数的定义希望使用draw()函数绘制不同对象draw()函数必须在基类中被声明为虚函数virtualvoiddraw()//基类中的虚函数{cout绘制基本形状\n;}8虚函数的覆盖派生类替换基类提供的虚函数实现编译器确保调用函数的正确版本9演示使用虚函数演示前面的例子10注意要点virtual关键字虚函数必须在声明它的类中有定义在派生类中重新定义的虚函数必须具有相同的参数11纯虚函数2-1基类无法(或没有必要)提供虚函数的实现将虚函数声明为纯虚函数virtualvoidprint()=0;12纯虚函数2-2派生类要创建对象,必须实现纯虚函数不能创建含有纯虚函数的类的对象13抽象类2-1包含纯虚函数的类只能用作基类不能创建抽象类的对象class类名{virtual类型函数名(参数表)=0;};14抽象类2-2继承了抽象类而没有提供纯虚函数的实现,这个类也是抽象类抽象类提供接口而不暴露实现细节在许多商业用途的库和应用程序框架中使用15动态绑定2-1成员函数调用中代码地址的确定非虚成员函数是根据指向对象的指针的类型静态地(在编译时)选择虚成员函数是动态(在运行时)解析的。根据对象的类型而不是根据指向对象的指针的类型来动态地(在运行时)选择16动态绑定2-2使用虚函数,系统将使用动态绑定在程序设计中提供更强的功能和灵活性处理过程中占用一些开销17虚析构函数2-1调用析构函数是为了释放由构造函数分配的内存空间如果基类的析构函数是非虚的,则不能用指向派生类的指针调用派生类的析构函数需要虚析构函数18虚析构函数2-2虚函数绑定到与对象所属的类,而不是与指针所对应的类派生类的实例总是包含一个基类的实例需要调用这两个类的析构函数以确保所有空间都被释放注意:构造函数不能是虚函数19示例2-1#includeiostream.hclassAlpha{private:char*alpha_ptr;public:Alpha()//构造函数不能是虚函数{alpha_ptr=newchar[5];}virtual~Alpha()//虚析构函数{delete[]alpha_ptr;coutAlpha的析构函数endl;}};20示例2-2classBeta:publicAlpha{private:char*ptrderived;public:Beta(){ptrderived=newchar[100];}~Beta(){delete[]ptrderived;coutBeta的析构函数endl;}};voidmain(){Alpha*ptr=newBeta;deleteptr;}21总结虚函数纯虚函数抽象类动态绑定虚析构函数