精华内容
下载资源
问答
  • 虚函数和抽象类

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

    虚函数是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;

    }

    展开全文
  • 虚函数、抽象函数、抽象类、接口

    千次阅读 2013-04-25 12:55:53
    1. Java虚函数 虚函数的存在是为了多态。 C++普通成员函数加上virtual关键字就成为虚函数 Java其实没有虚函数的概念,它...PS: 其实C++Java在虚函数的观点大同小异,异曲同工罢了。   2. Java抽象函数

    1. Java虚函数

    虚函数的存在是为了多态。

    C++中普通成员函数加上virtual关键字就成为虚函数

    Java中其实没有虚函数的概念,它的普通函数就相当于C++的虚函数,动态绑定是Java的默认行为。如果Java中不希望某个函数具有虚函数特性,可以加上final关键字变成非虚函数

    PS: 其实C++和Java在虚函数的观点大同小异,异曲同工罢了。

     

    2. Java抽象函数(纯虚函数)

       抽象函数或者说是纯虚函数的存在是为了定义接口。

       C++中纯虚函数形式为:virtual void print() = 0;

       Java中纯虚函数形式为:abstract void print();

       PS: 在抽象函数方面C++和Java还是换汤不换药。

     

    3. Java抽象类

    抽象类的存在是因为父类中既包括子类共性函数的具体定义,也包括需要子类各自实现的函数接口。抽象类中可以有数据成员和非抽象方法。

    C++中抽象类只需要包括纯虚函数,既是一个抽象类。如果仅仅包括虚函数,不能定义为抽象类,因为类中其实没有抽象的概念。

    Java抽象类是用abstract修饰声明的类。

    PS: 抽象类其实是一个半虚半实的东西,可以全部为虚,这时候变成接口。

     

    4. Java接口

    接口的存在是为了形成一种规约。接口中不能有普通成员变量,也不能具有非纯虚函数。

    C++中接口其实就是全纯虚的抽象类(虚基类)。

    Java中接口是用interface修饰的类。

    PS: 接口就是虚到极点的抽象类。

     

    5. 小结

    C++虚函数    ==  Java普通函数

    C++纯虚函数  ==  Java抽象函数

    C++抽象类    ==  Java抽象类

    C++虚基类    ==  Java接口


    抽象类往往用来表征我们在对问题领域进行分析、 设计中得出的抽象概念,是对一系列看上去不同,但是本质上相同的具体概念的抽象,我们不能把它们实例化(拿不出一个具体的东西)所以称之为抽象。
      比如:我们要描述“水果”,它就是一个抽象,它有质量、体积等一些共性(水果有质量),但又缺乏特性(苹果、橘子都是水果,它们有自己的特性),我们拿不出唯一一种能代表水果的东西(因为苹果、橘子都不能代表水果),可用抽象类来描述它,所以抽象类是不能够实例化的。当我们用某个类来具体描述“苹果”时,这个类就可以继承描述“水果”的抽象类,我们都知道“苹果”是一种“水果”。


    抽象类(abstract class)的定义方式如下: 
    public abstract class AbstractClass             //里面至少有一个抽象方法
    {
       public int t;  //普通数据成员
       public abstract void method1();   //抽象方法,抽象类的子类在类中必须实现抽象类中的抽象方法
       public abstract void method2(); 
       public void method3();   //非抽象方法
       public int method4();
       publi int method4 (){
            …… //抽象类中可以赋予非抽象方法方法的默认行为,即方法的具体实现
       }

           public void method3(){
            …… //抽象类中可以赋予非抽象方法方法的默认行为,即方法的具体实现
       } 

    }

     

    接口(interface)的定义方式如下: 
    public interface Interface

       static final int i;  //接口中不能有普通数据成员,只能够有静态的不能被修改的数据成员,static表示全局,final表示不可修改,可以不用static final 修饰,会隐式的声明为static和final
       

       public void method1();  //接口中的方法一定是抽象方法,所以不用abstract修饰
       

       public void method2();  //接口中不能赋予方法的默认行为,即不能有方法的具体实现
    }

      

      抽象类是一种功能不全的类,接口只是一个抽象方法声明和静态不能被修改的数据的集合,两者都不能被实例化。
      接口是一种特殊形式的抽象类,在java语言中抽象类表示的是一种继承关系,一个类只能继承一个抽象类,却可以实现多个接口。在许多情况下,接口确实可以代替抽象类,如果你不需要刻意表达属性上的继承的话。


    抽象类与接口的区别:

    1.
    接口是公开(public)的,里面不能有私有的方法或变量,是用于让别人使用的,实现接口的一定要实现接口里定义的所有方法。
    而抽象类是可以有私有方法或私有变量的,实现抽象类可以有选择地重写需要用到的方法,但是必须实现里面所有的抽象方法。
    2.
    抽象类在 Java 语言中表示的是一种继承关系,一个类只能使用一次继承关系。
    但是,一个类却可以实现多个interface(java中实现多重继承的方法之一)。
    3.
    抽象类中可以有自己的数据成员,也可以有非abstarct的成员方法。
    而在接口中,只能够有静态的不能被修改的数据成员(也就是必须是 static final的,不过在 interface中一般不定义数据成员),而且所有的成员方法都是抽象的。
    4.
    抽象类和接口所反映出的设计理念不同。
    其实abstract class表示的是"is-a"关系,interface表示的是"like-a"关系。(组合是"has a"关系)
    5.
    接口中定义的变量默认是public static final 型,且必须给其初值,所以实现类中不能重新定义,也不能改变其值。
    抽象类中的变量默认是 friendly 型,其值可以在子类中重新定义,也可以重新赋值。

    一般的应用里,最顶级的是接口,然后是抽象类实现接口,最后才到具体类实现。不是很建议具体类直接实现接口的。还有一种设计模式是面向接口编程,而非面向实现编程。


    展开全文
  • c++虚函数和抽象类

    2010-03-18 16:44:00
    虚函数又分为:普通虚函数和纯虚函数。纯虚函数是一种特殊的虚函数,它的一般格式如下: class { virtual ()=0; … }; 在许多情况下,在基类不能对虚函数给出有意义有实现,而把它说明为纯虚函数,它的实现...

    虚函数是c++实现多态的一种机制,基类的虚函数可以有子类的函数重新定义,从而实现函数功能的灵活性。

    虚函数又分为:普通虚函数和纯虚函数。

    纯虚函数是一种特殊的虚函数,它的一般格式如下:

        class <类名>
        {
            virtual <类型><函数名>(<参数表>)=0;
            …
        };

        在许多情况下,在基类中不能对虚函数给出有意义有实现,而把它说明为纯虚函数,它的实现留给该基类的派生类去做。这就是纯虚函数的作用。

     

    抽象类

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

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

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

        抽象类只能作为基类来使用,其纯虚函数的实现由派生类给出。如果派生类没有重新定义纯虚函数,而派生类只是继承基类的纯虚函数,则这个派生类仍然还是一个抽象类。如果派生类中给出了基类纯虚函数的实现,则该派生类就不再是抽象类了,它是一个可以建立对象的具体类了。 
       在有些情况下不想把基类置为抽象类,增加子类功能的灵活性,使用纯虚函数就不够方便了,可以使用普通虚函数而把方法体置空,格式如下:

          class <类名>
        {
            virtual <类型><函数名>(<参数表>) { }
            …
        };

    这样子类就可以选择性的重定义函数体,同时也保证了类本身不是抽象类,增加灵活性。

    展开全文
  • 只要是学过C++的人都知道在Base中加了Virtual关键字的函数就是虚拟函数(例如函数print),于是在 Base的派生Derived就可以通过重写虚拟函数来实现对基类虚拟函数的覆盖。当基类Base的指针point指向派生...

     关键字 Virtual

    Virtual是C++ OO机制中很重要的个关键字。只要是学过C++的人都知道在类Base中加了Virtual关键字的函数就是虚拟函数(例如函数print),于是在 Base的派生类Derived中就可以通过重写虚拟函数来实现对基类虚拟函数的覆盖。当基类Base的指针point指向派生类Derived的对象 时,对point的print函数的调用实际上是调用了Derived的print函数而不是Base的print函数。这是面向对象中的多态性的体现。 (关于虚拟机制是如何实现的,参见Inside the C++ Object Model ,Addison Wesley 1996)

    //---------------------------------------------------------
    class Base
    {
    public:Base(){}
    public:
           virtual void print(){cout<<"Base";}
    };
     
    class Derived:public Base
    {
    public:Derived(){}
    public:
           void print(){cout<<"Derived";}
    };
     
    int main()
    {
           Base *point=new Derived();
           point->print();
    }
    //---------------------------------------------------------
    Output:
    Derived
    //---------------------------------------------------------
    这也许会使人联想到函数的重载,但稍加对比就会发现两者是完全不同的:
    (1)       重载的几个函数必须在同一个类中;
    覆盖的函数必须在有继承关系的不同的类中
    (2)       覆盖的几个函数必须函数名、参数、返回值都相同;
    重载的函数必须函数名相同,参数不同。参数不同的目的就是为了在函数调用的时候编译器 能够通过参数来判断程序是在调用的哪个函数。这也就很自然地解释了为什么函数不能通过返回值不同来重载,因为程序在调用函数时很有可能不关心返回值,编译 器就无法从代码中看出程序在调用的是哪个函数了。
    (3)       覆盖的函数前必须加关键字Virtual;
    重载和Virtual没有任何瓜葛,加不加都不影响重载的运作。
     
    关于C++的隐藏规则:
    我曾经听说过C++的隐藏规则:
    1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual
    关键字,基类的函数将被隐藏(注意别与重载混淆)。
    2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual
    关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)。
                                                   ----------引用自《高质量C++/C 编程指南》林锐  2001
    这里,林锐博士好像犯了个错误。C++并没有隐藏规则,林锐博士所总结的隐藏规则是他错误地理解C++多态性所致。下面请看林锐博士给出的隐藏规则的例证:
    //------------------------------------------------------
    #include <iostream.h>
    class Base
    {
    public:
    virtual void f(float x){ cout << "Base::f(float) " << x << endl; }
    void g(float x){ cout << "Base::g(float) " << x << endl; }
    void h(float x){ cout << "Base::h(float) " << x << endl; }
    };
     
    class Derived : public Base
    {
    public:
    virtual void f(float x){ cout << "Derived::f(float) " << x << endl; }
    void g(int x){ cout << "Derived::g(int) " << x << endl; }
    void h(float x){ cout << "Derived::h(float) " << x << endl; }
    };
     
    void main(void)
    {
    Derived d;
    Base *pb = &d;
    Derived *pd = &d;
    // Good : behavior depends solely on type of the object
    pb->f(3.14f); // Derived::f(float) 3.14
    pd->f(3.14f); // Derived::f(float) 3.14
    // Bad : behavior depends on type of the pointer
    pb->g(3.14f); // Base::g(float) 3.14
    pd->g(3.14f); // Derived::g(int) 3 (surprise!)
    // Bad : behavior depends on type of the pointer
    pb->h(3.14f); // Base::h(float) 3.14 (surprise!)
    pd->h(3.14f); // Derived::h(float) 3.14
    }
    //---------------------------------------------------------
    林锐博士认为bp 和dp 指向同一地址,按理说运行结果应该是相同的,而事实上运行结果不同,所以他把原因归结为C++的隐藏规则,其实这一观点是错的。决定bp和dp调用函数运行结果的不是他们指向的地址,而是他们的指针类型。“只有在通过基类指针或引用间接指向派生类子类型时多态性才会起作用”(C++ Primer 3rd Edition)。pb是基类指针,pd是派生类指针,pd的所有函数调用都只是调用自己的函数,和多态性无关,所以pd的所有函数调用的结果都输出Derived::是完全正常的;pb 的函数调用如果有virtual则根据多态性调用派生类的,如果没有virtual则是正常的静态函数调用,还是调用基类的,所以有virtual的f函 数调用输出Derived::,其它两个没有virtual则还是输出Base::很正常啊,nothing surprise!
    所以并没有所谓的隐藏规则,虽然《高质量C++/C 编程指南》是本很不错的书,可大家不要迷信哦。记住“只有在通过基类指针或引用间接指向派生类子类型时多态性才会起作用”。

    虚函数

    是c++实现多态的一种机制,基类的虚函数可以有子类的函数重新定义,从而实现函数功能的灵活性。

    虚函数又分为:普通虚函数和纯虚函数。

    纯虚函数是一种特殊的虚函数,它的一般格式如下:

        class <类名>
        {
            virtual <类型><函数名>(<参数表>)=0;
            …
        };
    
     在许多情况下,在基类中不能对虚函数给出有意义有实现,而把它说明为纯虚函数,它的实现留给该基类的派生类去做。这就是纯虚函数的作用。

     

    C++语言为我们提供了一种语法结构,通过它可以指明,一个虚拟函数只是提供了一个可被子类型改写的接口。但是,它本身并不能通过虚拟机制被调用。这就是纯虚拟函数(pure
    virtual function)。 纯虚拟函数的声明如下所示:
    class Query {
    public:
    // 声明纯虚拟函数
    virtual ostream& print( ostream&=cout ) const = 0;
    // ...
    };
    这里函数声明后面紧跟赋值0。
    包含(或继承)一个或多个纯虚拟函数的类被编译器识别为抽象基类。试图创建一个抽象基类的独立类对象会导致编译时刻错误。(类似地通过虚拟机制调用纯虚拟函数也是错误的例如)
    // Query 声明了纯虚拟函数
    // 所以, 程序员不能创建独立的 Query 类对象
    // ok: NameQuery 中的 Query 子对象
    Query *pq = new NameQuery( "Nostromo" );
    // 错误: new 表达式分配 Query 对象
    Query *pq2 = new Query;
    抽象基类只能作为子对象出现在后续的派生类中。
     
     
    如果只知道virtual加在函数前,那对virtual只了解了一半,virtual还有一个重要用法是virtual public,就是虚拟继承。虚拟继承在C++ Primer中有详细的描述,下面稍作修改的阐释一下:
    在缺省情况下C++中的继承是“按值组合”的一种特殊情况。当我们写
    class Bear : public ZooAnimal { ... };
    每个Bear 类对象都含有其ZooAnimal 基类子对象的所有非静态数据成员以及在Bear中声明的非静态数据成员类似地当派生类自己也作为一个基类对象时如:
    class PolarBear : public Bear { ... };
    则PolarBear 类对象含有在PolarBear 中声明的所有非静态数据成员以及其Bear 子对象的所有非静态数据成员和ZooAnimal 子对象的所有非静态数据成员。在单继承下这种由继承支持的特殊形式的按值组合提供了最有效的最紧凑的对象表示。在多继承下当一个基类在派生层次中出现多次 时就会有问题最主要的实际例子是iostream 类层次结构。ostream 和istream 类都从抽象ios 基类派生而来,而iostream 类又是从ostream 和istream 派生
    class iostream :public istream, public ostream { ... };
    缺省情况下,每个iostream 类对象含有两个ios 子对象:在istream 子对象中的实例以及在ostream 子对象中的实例。这为什么不好?从效率上而言,存储ios 子对象的两个复本,浪费了存储区,因为iostream 只需要一个实例。而且,ios 构造函数被调用了两次每个子对象一次。更严重的问题是由于两个实例引起的二义性。例如,任何未限定修饰地访问ios 的成员都将导致编译时刻错误:到底访问哪个实例?如果ostream 和istream 对其ios 子对象的初始化稍稍不同,会怎样呢?怎样通过iostream 类保证这一对ios 值的一致性?在缺省的按值组合机制下,真的没有好办法可以保证这一点。
    C++语言的解决方案是,提供另一种可替代按“引用组合”的继承机制虚拟继承(virtual inheritance )在虚拟继承下只有一个共享的基类子对象被继承而无论该基类在派生层次
    中出现多少次共享的基类子对象被称为虚拟基类。
           通过用关键字virtual 修政一个基类的声明可以将它指定为被虚拟派生。例如,下列声明使得ZooAnimal 成为Bear 和Raccoon 的虚拟基类:
    // 关键字 public 和 virtual
    // 的顺序不重要
    class Bear : public virtual ZooAnimal { ... };
    class Raccoon : virtual public ZooAnimal { ... };
    虚拟派生不是基类本身的一个显式特性,而是它与派生类的关系如前面所说明的,虚拟继承提供了“按引用组合”。也就是说,对于子对象及其非静态成 员的访问是间接进行的。这使得在多继承情况下,把多个虚拟基类子对象组合成派生类中的一个共享实例,从而提供了必要的灵活性。同时,即使一个基类是虚拟 的,我们仍然可以通过该基类类型的指针或引用,来操纵派生类的对象。

    抽象类

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

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

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

        抽象类只能作为基类来使用,其纯虚函数的实现由派生类给出。如果派生类没有重新定义纯虚函数,而派生类只是继承基类的纯虚函数,则这个派生类仍然还是一个抽象类。如果派生类中给出了基类纯虚函数的实现,则该派生类就不再是抽象类了,它是一个可以建立对象的具体类了。 
       在有些情况下不想把基类置为抽象类,增加子类功能的灵活性,使用纯虚函数就不够方便了,可以使用普通虚函数而把方法体置空,格式如下:

          class <类名>
        {
            virtual <类型><函数名>(<参数表>) { }
            …
        };
    
    


    这样子类就可以选择性的重定义函数体,同时也保证了类本身不是抽象类,增加灵活性。

    接口:

    c++中没有接口的概念,与之对应的是纯虚类,即只含有纯虚函数的类,c++抽象类的概念是含有纯虚函数成员的类。这是因为c++提供多继承,而像java、c#这些只提供单继承(避免多继承的复杂性和低效性)的语言为了模拟多继承功能就提供了接口概念,接口可以继承多个。

    但是如果一个类,所有的成员都是纯虚函数,那么它和一般的抽象类在用法上是有区别的。至少microsoft给的com接口定义全部都是仅由纯虚函数构成的类。因此把这样的类定义叫做纯虚类也不算错。

       在java里面的确没有纯虚类的概念,因为java里没有纯虚函数这个概念。java管虚函数叫做abstract function,管抽象类叫做abstract class,直接说来,java根本没有virtual这个关键字,都用abstract代替,因此java里面根本就没有pure这个概念。有那就是interface。在interface里面定义的函数都不能有函数体,这个在java里面叫做接口。那么c++里面与interface等同的概念就是纯虚类了,c++用纯虚类来模拟interface这个抽象概念,因此这里说的“纯虚类”与java的abstract class不同,与c++的一般抽象类也不同。“纯虚类”与c++一般抽象类的区别就好比java里面interface 和 abstract class的区别。

    展开全文
  • C++——虚函数抽象类

    千次阅读 2018-12-28 10:57:37
    虚函数 虚函数:(virtual function)允许函数调用与函数体间的联系在运行时才建立,是实现动态联编的基础。...如果派生类中没有重新定义虚函数,基类虚函数充当派生虚函数。 要由成员函数、指针或引...
  • C#抽象类、接口、虚函数和抽象函数

    千次阅读 2014-11-08 15:42:17
    C#抽象类和接口 转载自:http://blog.csdn.net/lwk2011/article/details/5974383 抽象类和接口的异同 一、抽象类:  抽象类是特殊的类,只是不能被实例化;除此以外,具有类的其他特性;重要的是抽象类可以...
  • 多态:是对于不同对象接收相同消息时产生不同的动作。C++的多态性具体体现在运行...允许在派生类中对基类的虚函数重新定义。 虚函数是运行时多态,若某个基类函数声明为虚函数,则其公有派生将定义与其基类虚函数原型
  • 这里,同样的消息理解为【对成员同名函数的调用】,而不同的行为则是产生不同的输出结果。例如在运算符重载,同样是调用“+”,但是结果可以是int,float等等。  系统的角度来说,多态性分为静态多态性(编译多态性)...
  • 由这两个问题开始深入的理解一下虚函数,纯虚函数以及抽象类和接口之间的关系。 虚函数 百度定义:简单地说,那些被virtual关键字修饰的成员函数,就是虚函数虚函数的作用,用专业术语来解释就是实现多态性...
  • 纯虚函数和抽象类

    2020-08-22 12:36:31
    抽象类的成员函数内部可以调用纯虚函数(多态),而在构造析构函数内部不能调用纯虚函数(非多态,抽象类中的该函数函数体,不可调用) 1.纯虚函数抽象类 C++的纯虚函数(或抽象函数)
  • 虚函数:由virtual,它允许在派生类中被重写,要重写方法,必须先声明为virtual public class myclass {  public virtual int myint()  {  函数体;  } } class myclass1:myclass {  public ...
  • 多态性就是允许将子类类型的指针赋值给父类类型的指针,多态是通过虚函数实现的。 多态可以让父类的指针有“多种形态”,这是一种泛型技术。(所谓泛型技术,就是试图使用不变的代码来实现可变的算法)。 2. ...
  • 虚函数抽象类的区别

    千次阅读 2012-03-31 10:30:01
    您查询的关键词是:虚函数纯虚函数 。如果打开速度慢,可以尝试快速版;如果想保存快照,可以添加到搜藏;如果想更新或删除快照,可以投诉快照。 (百度网页...
  • 说明:接口其实就是程序之间的一种协定,用来约束一组相关的行为。...我们要描述这三种动物,如果采用虚函数的形式,则无法解决游泳函数问题 using System; class dongwu //基类 { virtual public void youyong() //
  • 多态性就是允许将子类类型的指针赋值给父类类型的指针,多态是通过虚函数实现的。 多态可以让父类的指针有“多种形态”,这是一种泛型技术。(所谓泛型技术,就是试图使用不变的代码来实现可变的算法)。 2. 虚函数 ...
  • C++,实现多态有以下方法:虚函数抽象类,重载,覆盖 多态性在Object PascalC++中都是通过虚函数(Virtual Function) 实现的。 这么一大堆名词,实际上就围绕一件事展开,就是多态,其他三个名词都是为...
  • abstract class是抽象类,至少包含一个纯虚函数的类就叫做抽象类。 ...纯虚函数和虚函数的区别在于前者不包含定义,而后者包含函数体。 那么纯虚类就是不包含任何实现(包括成员函数定义成员
  • 这么一大堆名词,实际上就围绕一件事展开,就是多态,其他三个名词都是为实现C++的多态机制而提出的一些规则,下面分两部分介绍,第一部分介绍【多态】,第二部分介绍【虚函数,纯虚函数,抽象类】一 【多态】多态的...
  • 多态性就是允许将子类类型的指针赋值给父类类型的指针,多态是通过虚函数实现的。 多态可以让父类的指针有“多种形态”,这是一种泛型技术。(所谓泛型技术,就是试图使用不变的代码来实现可变的算法)。 实际上,...
  • abstract class是抽象类,至少包含一个纯虚函数的类就叫做抽象类。 ...纯虚函数和虚函数的区别在于前者不包含定义,而后者包含函数体。 那么纯虚类就是不包含任何实现(包括成员函数定义成员
  • 1.函数重载 由静态联编支持的多态性称为编译时的多态性或静态多态性,也就是说,确定同名操作的具体操作对象的过程是在编译过程完成的。...在C++,可以用虚函数来实现运行时的多态性。 2.
  • /* (程序头部注释开始) ...* 文件名称:虚函数抽象类的应用 * 作 者: 张培培 * 完成日期: 2012年 05月 10日 * 版 本 号: * 对任务及求解方法的描述部分 * 输入描述: * 问题描述:  * 程序输出:
  • 1. 析构函数和虚析构函数 如果基类的析构函数的,那么它的派生的析构函数都是的 这将导致:当派生析构的时候,它的所有的基类的析构函数都将得到调用 否则,只调用派生的析构函数(这可能导致基类的...
  • 1.函数重载 由静态联编支持的多态性称为编译时的多态性或静态多态性,也就是说,确定同名操作的具体操作对象的过程是在编译过程完成的。...在C++,可以用虚函数来实现运行时的多态性。 2.1.虚函数定义

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 29,717
精华内容 11,886
关键字:

关于虚函数和抽象类的描述中