C++纯虚函数
一、定义
纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加“=0” virtual void funtion1()=0二、引入原因
1、为了方便使用多态特性,我们常常需要在基类中定义虚拟函数。 2、在很多情况下,基类本身生成对象是不合情理的。例如,动物作为一个基类可以派生出老虎、孔雀等子类,但动物本身生成对象明显不合常理。 为了解决上述问题,引入了纯虚函数的概念,将函数定义为纯虚函数(方法:virtual ReturnType Function()= 0;),则编译器要求在派生类中必须予以重写以实现多态性。同时含有纯虚拟函数的类称为抽象类,它不能生成对象。这样就很好地解决了上述两个问题。三、相似概念
1、多态性 指相同对象收到不同消息或不同对象收到相同消息时产生不同的实现动作。C++支持两种多态性:编译时多态性,运行时多态性。 a.编译时多态性:通过重载函数实现 b 运行时多态性:通过虚函数实现。 2、虚函数 虚函数是在基类中被声明为virtual,并在派生类中重新定义的成员函数,可实现成员函数的动态重载 3、抽象类 包含纯虚函数的类称为抽象类。由于抽象类包含了没有定义的纯虚函数,所以不能定义抽象类的对象。程序举例
基类:class A { public: A(); void f1(); virtual void f2(); virtual void f3()=0; virtual ~A(); };
子类:class B : public A { public: B(); void f1(); void f2(); void f3(); virtual ~B(); };
主函数:int main(int argc, char* argv[]) { A *m_j=new B(); m_j->f1(); m_j->f2(); m_j->f3(); delete m_j; return 0; }
f1()是一个普通的重载. 调用m_j->f1();会去调用A类中的f1(),它是在我们写好代码的时候就会定好的. 也就是根据它是由A类定义的,这样就调用这个类的函数. f2()是虚函数. 调用m_j->f2();会调用m_j所指的对象中,对应的这个函数.这是由于new的B对象. f3()与f2()一样,只是在基类中不需要写函数实现.
接口是一个没有被实现的特殊的类,它是一系列操作的集合,我们可以把它看作是与其他对象通讯的协议。C++中没有提供类似interface这样的关键 字来定义接口,但是Mircrosoft c++中提供了__declspec(novtable)来修饰一个类,来表示该类没有虚函数表,也就是虚函数都是纯虚的,接口中的纯虚函数在继承时都要被实现。利用__declspec(novtable)我们依然可以定义一 个接口。代码例子如下:
#include <IOSTREAM> using namespace std; #define interface class __declspec(novtable) interface ICodec { public: virtual bool Decode(char * lpDataSrc,unsigned int nSrcLen,char * lpDataDst,unsigned int *pnDstLen); virtual bool Encode(char * lpDataSrc,unsigned int nSrcLen,char * lpDataDst,unsigned int *pnDstLen); }; class CCodec : public ICodec { public: virtual bool Decode(char * lpDataSrc,unsigned int nSrcLen,char * lpDataDst,unsigned int *pnDstLen) { cout << "解码..." << endl; return true; } virtual bool Encode(char * lpDataSrc,unsigned int nSrcLen,char * lpDataDst,unsigned int *pnDstLen) { cout << "编码..." << endl; return true; } }; int main(int argc, char* argv[]) { ICodec * pCodec = new CCodec(); pCodec->Decode(NULL,0,NULL,NULL); pCodec->Encode(NULL,0,NULL,NULL); delete (CCodec*)pCodec; return 0; }
上面的ICodec接口等价于下面的定义:class ICodec { public: virtual bool Decode(char * lpDataSrc,unsigned int nSrcLen,char * lpDataDst,unsigned int *pnDstLen)=0; virtual bool Encode(char * lpDataSrc,unsigned int nSrcLen,char * lpDataDst,unsigned int *pnDstLen)=0; };