虚函数和抽象类

来源:互联网 发布:java数组的作用 编辑:程序博客网 时间:2024/04/29 06:45

虚函数是C++多态的一种表现 ,例如:子类继承了父类的一个函数(方法),而我们把父类的指针指向子类,则必须把父类的该函数(方法)设为virturl(虚函数)。 使用虚函数,我们可以灵活的进行动态绑定,当然是以一定的开销为代价。

        如果父类的函数(方法)根本没有必要或者无法实现,完全要依赖子类去实现的话,可以把此函数(方法)设为virturl 函数名=0 。我们把这样的函数(方法)称为纯虚函数。 如果一个类包含了纯虚函数,称此类为抽象类。

一、定义.

纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加“=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++里,就是使用继承和多态来实现这种思想。   如果你想让基类为派生类提供缺省的处理方法,那么把这个函数设成虚函数;如果你必须让派生类重新定义该虚函数,那么就把他弄成纯虚的。

   
抽象类

    带有纯虚函数的类称为抽象类。抽象类是一种特殊的类,它是为了抽象和设计的目的而建立的,它处于继承层次结构的较上层。抽象类是不能定义对象的,在实际中为了强调一个类是抽象类,可将该类的构造函数说明为保护的访问控制权限。

    抽象类的主要作用是将有关的组织在一个继承层次结构中,由它来为它们提供一个公共的根,相关的子类是从这个根派生出来的。

    抽象类刻画了一组子类的操作接口的通用语义,这些语义也传给子类。一般而言,抽象类只描述这组子类共同的操作接口,而完整的实现留给子类。

    抽象类只能作为基类来使用,其纯虚函数的实现由派生类给出。如果派生类没有重新定义纯虚函数,而派生类只是继承基类的纯虚函数,则这个派生类仍然还是一个抽象类。如果派生类中给出了基类纯虚函数的实现,则该派生类就不再是抽象类了,它是一个可以建立对象的具体类了。

1. 虚函数和纯虚函数可以定义在同一个类(class)中,含有纯虚函数的类被称为抽象类(abstract class),而只含有虚函数的类(class)不能被称为抽象类(abstract class)。

   2. 虚函数可以被直接使用,也可以被子类(sub class)重载以后以多态的形式调用,而纯虚函数必须在子类(sub class)中实现该函数才可以使用,因为纯虚函数在基类(base class)
只有声明而没有定义。

   3. 虚函数和纯虚函数都可以在子类(sub class)中被重载,以多态的形式被调用。

   4. 虚函数和纯虚函数通常存在于抽象基类(abstract base class -ABC)之中,被继承的子类重载,目的是提供一个统一的接口。

   5. 虚函数的定义形式:virtual    {method body} 
       纯虚函数的定义形式:virtual    { } = 0; 
      在虚函数和纯虚函数的定义中不能有static标识符,原因很简单,被static修饰的函数在编译时候要求前期bind,然而虚函数却是动态绑定(run-time bind),而且被两者修饰的函数生命周期(life recycle)也不一样。
   6. 如果一个类中含有纯虚函数,那么任何试图对该类进行实例化的语句都将导致错误的产生,因为抽象基类(ABC)是不能被直接调用的。必须被子类继承重载以后,根据要求调用其子类的方法。

       以下为一个简单的虚函数和纯虚寒数的使用演示,目的是抛砖引玉!
#include 

//father class
class Virtualbase
{
public:
        virtual   void Demon()= 0;        //prue virtual function
        virtual   void Base() {cout<<"this is farther class"<};
//sub class
class SubVirtual :public Virtualbase
{
public:
    void Demon() { cout<<" this is SubVirtual!"<<endl;  

     void Base() { cout<<"this is subclass Base"<<endl;

};
/*           instance class and sample                 */
void main()
{
        Virtualbase* inst = new SubVirtual(); //multstate pointer
        inst->Demon();
        inst->Base();
//   inst = new Virtualbase();
//        inst->Base();
        return  0;

}

0 0