精华内容
下载资源
问答
  • 虚函数 纯虚函数

    2019-09-24 21:24:36
    1.虚函数(impure virtual)  C++的虚函数主要作用是“运行时多态”,父类中提供虚函数的实现,为子类提供默认的函数实现。  子类可以重写父类的虚函数实现子类的特殊化。  如下就是一个父类中的虚函数: ...

    1.虚函数(impure virtual)

      C++的虚函数主要作用是“运行时多态”,父类中提供虚函数的实现,为子类提供默认的函数实现。

      子类可以重写父类的虚函数实现子类的特殊化。

      如下就是一个父类中的虚函数:

    复制代码
    class A
    {
    public:
        virtual void out2(string s)
        {
            cout<<"A(out2):"<<s<<endl;
        }
    };
    复制代码

    2.纯虚函数(pure virtual)

      C++中包含纯虚函数的类,被称为是“抽象类”。抽象类不能使用new出对象,只有实现了这个纯虚函数的子类才能new出对象。

      C++中的纯虚函数更像是“只提供申明,没有实现”,是对子类的约束,是“接口继承”。

      C++中的纯虚函数也是一种“运行时多态”。

      如下面的类包含纯虚函数,就是“抽象类”:

    复制代码
    class A
    {
    public:
        virtual void out1(string s)=0;
        virtual void out2(string s)
        {
            cout<<"A(out2):"<<s<<endl;
        }
    };
    复制代码

    3.普通函数(no-virtual)

      普通函数是静态编译的,没有运行时多态,只会根据指针或引用的“字面值”类对象,调用自己的普通函数。

      普通函数是父类为子类提供的“强制实现”。

      因此,在继承关系中,子类不应该重写父类的普通函数,因为函数的调用至于类对象的字面值有关。

    4.程序综合实例

    复制代码
    #include <iostream>
    using namespace std;
    
    class A
    {
    public:
        virtual void out1()=0;  ///由子类实现
        virtual ~A(){};
        virtual void out2() ///默认实现
        {
            cout<<"A(out2)"<<endl;
        }
        void out3() ///强制实现
        {
            cout<<"A(out3)"<<endl;
        }
    };
    
    class B:public A
    {
    public:
        virtual ~B(){};
        void out1()
        {
            cout<<"B(out1)"<<endl;
        }
        void out2()
        {
            cout<<"B(out2)"<<endl;
        }
        void out3()
        {
            cout<<"B(out3)"<<endl;
        }
    };
    
    int main()
    {
        A *ab=new B;
        ab->out1();
        ab->out2();
        ab->out3();
        cout<<"************************"<<endl;
        B *bb=new B;
        bb->out1();
        bb->out2();
        bb->out3();
    
        delete ab;
        delete bb;
        return 0;
    }
    复制代码

    执行结果:

     

     -------------------------------------------------------------------------------------------

    虚函数为了重载和多态的需要,在基类中是有定义的,即便定义是空,所以子类中可以重写也可以不写基类中的此函数!
    纯虚函数在基类中是没有定义的,必须在子类中加以实现,很像java中的接口函数!
    虚函数
    引入原因:为了方便使用多态特性,我们常常需要在基类中定义虚函数。
    class Cman
    {
    public:
    virtual void Eat(){……};
    void Move();
    private:
    };
    class CChild : public CMan
    {
    public:
    virtual void Eat(){……};
    private:
    };
    CMan m_man;
    CChild m_child;
    CMan *p ;//这才是使用的精髓,如果不定义基类的指针去使用,没有太大的意义
    p = &m_man ;
    p->Eat(); //始终调用CMan的Eat成员函数,不会调用 CChild 的
    p = &m_child;
    p->Eat();//如果子类实现(覆盖)了该方法,则始终调用CChild的Eat函数
    //不会调用CMan 的 Eat 方法;如果子类没有实现该函数,则调用CMan的Eat函数
    p->Move(); //子类中没有该成员函数,所以调用的是基类中的


    纯虚函数
    引入原因:
    1、同“虚函数”;
    2、在很多情况下,基类本身生成对象是不合情理的。例如,动物作为一个基类可以派生出老虎、孔雀等子类,但动物本身生成对象明显不合常理。
    纯虚函数就是基类只定义了函数体,没有实现过程,定义方法如: virtual void Eat() = 0; 不要 
    在cpp中定义;纯虚函数相当于接口,不能直接实例化,需要派生类来实现函数定义;
    有的人可能在想,定义这些有什么用啊 
    ,我觉得很有用,比如你想描述一些事物的属性给别人,而自己不想去实现,就可以定义为纯虚函数。说的再透彻一些。比如盖楼房,你是老板,你给建筑公司描述清楚你的楼房的特性,多少层,楼顶要有个花园什么的,建筑公司就可以按照你的方法去实现了,如果你不说清楚这些,可能建筑公司不太了解你需要楼房的特性。用纯需函数就可以很好的分工合作了
    虚函数和纯虚函数区别
    观点一:
    类里声明为虚函数的话,这个函数是实现的,哪怕是空实现,它的作用就是为了能让这个函数在它的子类里面可以被重载,这样的话,这样编译器就可以使用后期绑定来达到多态了
    纯虚函数只是一个接口,是个函数的声明而已,它要留到子类里去实现。
    class A{
    protected:
    void foo();//普通类函数
    virtual void foo1();//虚函数
    virtual void foo2() = 0;//纯虚函数
    }
    观点二:
    虚函数在子类里面也可以不重载的;但纯虚必须在子类去实现,这就像Java的接口一样。通常我们把很多函数加上virtual,是一个好的习惯,虽然牺牲了一些性能,但是增加了面向对象的多态性,因为你很难预料到父类里面的这个函数不在子类里面不去修改它的实现
    观点三:
    虚函数的类用于“实作继承”,继承接口的同时也继承了父类的实现。当然我们也可以完成自己的实现。纯虚函数的类用于“介面继承”,主要用于通信协议方面。关注的是接口的统一性,实现由子类完成。一般来说,介面类中只有纯虚函数的。
    观点四:
    带纯虚函数的类叫虚基类,这种基类不能直接生成对象,而只有被继承,并重写其虚函数后,才能使用。这样的类也叫抽象类。
    虚函数是为了继承接口和默认行为
    纯虚函数只是继承接口,行为必须重新定义

     

    转载于:https://www.cnblogs.com/xzh1993/p/10276001.html

    展开全文
  • 虚函数纯虚函数区别虚函数为了重载和多态的需要,在基类中是由定义的,即便定义是空,所以子类中可以重写也可以不写基类中的函数! 纯虚函数在基类中是没有定义的,必须在子类中加以实现,很像java中的接口函数!...

    虚函数与纯虚函数区别虚函数为了重载和多态的需要,在基类中是由定义的,即便定义是空,所以子类中可以重写也可以不写基类中的函数!

    纯虚函数在基类中是没有定义的,必须在子类中加以实现,很像java中的接口函数!

    虚函数

    引入原因:为了方便使用多态特性,我们常常需要在基类中定义虚函数。

    class Cman

    {

    public:

        virtual void Eat(){……};

        void Move();

    private:

    };

    class CChild : public CMan

    {

    public:

         virtual void Eat(){……};

    private:

    };

    CMan m_man;

    CChild m_child;

    //这才是使用的精髓,如果不定义基类的指针去使用,没有太大的意义

    CMan *p ;

    p = &m_man ;

    p->Eat(); //始终调用CMan的Eat成员函数,不会调用 CChild 的

    p = &m_child;

    p->Eat(); //如果子类实现(覆盖)了该方法,则始终调用CChild的Eat函数

    //不会调用CMan 的 Eat 方法 ;如果子类没有实现该函数,则调用CMan的Eat函数

    p->Move(); //子类中没有该成员函数,所以调用的是基类中的

    纯虚函数

    引入原因:

         1、同“虚函数”;

         2、在很多情况下,基类本身生成对象是不合情理的。例如,动物作为一个基类可以派生出老虎、孔雀等子类,但动物本身生成对象明显不合常理。

    //纯虚函数就是基类只定义了函数体,没有实现过程定义方法如下

    // virtual void Eat() = 0; 直接=0 不要 在cpp中定义就可以了

    //纯虚函数相当于接口,不能直接实例话,需要派生类来实现函数定义

    //有的人可能在想,定义这些有什么用啊 ,我觉得很有用

    //比如你想描述一些事物的属性给别人,而自己不想去实现,就可以定

    //义为纯虚函数。说的再透彻一些。比如盖楼房,你是老板,你给建筑公司

    //描述清楚你的楼房的特性,多少层,楼顶要有个花园什么的

    //建筑公司就可以按照你的方法去实现了,如果你不说清楚这些,可能建筑

    //公司不太了解你需要楼房的特性。用纯需函数就可以很好的分工合作了

    虚函数和纯虚函数区别

    观点一:

    类里声明为虚函数的话,这个函数是实现的,哪怕是空实现,它的作用就是为了能让这个函数在它的子类里面可以被重载,这样的话,这样编译器就可以使用后期绑定来达到多态了

    纯虚函数只是一个接口,是个函数的声明而已,它要留到子类里去实现。

    class A{

    protected:

        void foo();//普通类函数

        virtual void foo1();//虚函数

        virtual void foo2() = 0;//纯虚函数

    }

    观点二:

    虚函数在子类里面也可以不重载的;但纯虚必须在子类去实现,这就像Java的接口一样。通常我们把很多函数加上virtual,是一个好的习惯,虽然牺牲了一些性能,但是增加了面向对象的多态性,因为你很难预料到父类里面的这个函数不在子类里面不去修改它的实现

    观点三:

    虚函数的类用于“实作继承”,继承接口的同时也继承了父类的实现。当然我们也可以完成自己的实现。纯虚函数的类用于“介面继承”,主要用于通信协议方面。关注的是接口的统一性,实现由子类完成。一般来说,介面类中只有纯虚函数的。

    观点四:

    带纯虚函数的类叫虚基类,这种基类不能直接生成对象,而只有被继承,并重写其虚函数后,才能使用。这样的类也叫抽象类。

    虚函数是为了继承接口和默认行为

    纯虚函数只是继承接口,行为必须重新定义

    转载于:https://www.cnblogs.com/zhchongyao/archive/2010/02/23/1672143.html

    展开全文
  • c++虚函数定义:在某基类中声明为 virtual 并在一个或多个派生类中被重新定 义的成员函数[1]语法:virtual 函数返回类型 函数名(参数表) { 函数体 }用途:实现多态性,通过指向派生类的基类指针,访问派生类中同名...

    c++

    虚函数

    定义:在某基类中声明为 virtual 并在一个或多个派生类中被重新定 义的成员函数[1]

    语法:virtual 函数返回类型 函数名(参数表) { 函数体 }

    用途:实现多态性,通过指向派生类的基类指针,访问派生类中同名覆盖成员函数,也就是允许子类override父类同名方法。

    虚函数的作用是实现动态联编,也就是在程序的运行阶段动态地选择合适的成员函数,在定义了虚函数后,可以在基类的派生类中对虚函数重新定义,在派生类中重新定义的函数应与虚函数具有相同的形参个数和形参类型(也就是完全相同的方法,不能只是函数名相同。)。以实现统一的接口,不同的定义过程。如果在派生类中没有对虚函数重新定义,则它继承其基类的虚函数。

    当程序发现虚函数名前的关键字virtual后,会自动将其作为动态联编处理,即在程序运行时动态地选择合适的成员函数。虚函数是C++多态的一种表现。动态联编规定,只能通过指向基类的指针或基类对象的引用来调用虚函数,其格式:

    指向基类的指针变量名->虚函数名(实参表)

    基类对象的引用名. 虚函数名(实参表)

    使用虚函数,我们可以灵活的进行动态绑定,当然是以一定的开销为代价。如果父类的函数(方法)根本没有必要或者无法实现,完全要依赖子类去实现的话,可以把此函数(方法)设为virtual 函数名=0 ,例如:virtual void fun() = 0,我们把这样的函数(方法)称为纯虚函数。如果一个类包含了纯虚函数,称此类为抽象类。

    总结:如果一个子类想要重写父类的方法,那么父类的这个成员方法必须是virtual的,也就是这个方法必须是虚函数。

    java

    在java中,所有方法默认就是虚拟的,只要方法不是声明为final类型的,那么肯定就是虚函数,不用为方法显示声明为virtual。在中提到:"In Java, you do not need to declare a method as virtual. Dynamic binding is the default behavior. If you do not want a method to be virtual, you tag it as final"。所以我们发现,在java中,子类可以重写(override)父类的方法,而父类没有声明virtual。

    展开全文
  • c++中的 虚函数 纯虚函数 虚基类

    千次阅读 2018-06-27 21:23:06
    一、前言 原文转载自 ...二、虚函数 纯虚函数 虚基类三者区别 1.虚函数是用于多态中virtual修饰父类函数,确保父类指针调用子类对象时,运行子类函数的。 2.纯虚函数是用来定义接口的,也就是基类...

    一、前言

         原文转载自 https://blog.csdn.net/a345203172/article/details/21697687,为了理解下C++中虚函数 纯虚函数 虚基类的基础知识点。

    二、虚函数 纯虚函数 虚基类三者区别      

        1.虚函数是用于多态中virtual修饰父类函数,确保父类指针调用子类对象时,运行子类函数的。

        2.纯虚函数是用来定义接口的,也就是基类中定义一个纯虚函数,基类不用实现,让子类来实现。

        3.虚基类是用来在多继承中,如果父类继承自同一个父类,就只实例化一个父类(说的有点绕,就是只实例化一个爷爷的意思)

    2.1、虚函数

        这个和多态有关,多态的定义不清楚的话到其他地方先了解一下,多态的三个必要条件:1.继承 2.重载 3.父类指针指向子类对象。

    看一下程序

    第一个是没有使用virtual的,没有使用多态的:

    class A  
    {  
    public:  
        void printf(){  
            cout<<"printf A"<<endl;  
        }  
    };  
    class B : public A  
    {  
    public:  
        void printf(){  
            cout<<"printf B"<<endl;  
        }  
    };  
    int main(int argc, const char * argv[])  
    {  
        A *a = new A();  
        a->printf();  
        B *b = new B();  
        b->printf();  
        return 0;  
    }  

    结果:

    printf A

    printf B

    这是最基本的用法,没有多态,只有继承,下面是使用了多态但是没有引用virtual关键字的情况,多态的作用请参考其他地方的文章:

    int main(int argc, const char * argv[])  
    {  
        A *a = new B();  
        a->printf();  
        return 0;  
    }  
    结果:

    printf A

    因为类的定义都一样,所以就没再写出来了,当父类指针指向子类对象的时候,如果不使用virtual,父类调用方法的时候还是调用了父类自己的方法,没有调用子类重写的方法,所以就没有实现到多态的作用,我们再来在父类中试试加入virtual关键字看看:

    class A  
    {  
    public:  
    virtual void printf(){  
            cout<<"printf A"<<endl;  
        }  
    };  
    class B : public A  
    {  
    public:  
        void printf(){  
            cout<<"printf B"<<endl;  
        }  
    };  
    int main(int argc, const char * argv[])  
    {  
        A *a = new B();  
        a->printf();  
        return 0;  
    }  

    结果

    printf B

         virtual是加入到父类中的,子类的代码没改变,main函数还是父类指针指向子类对象,结果终于可以打印到子类重写的方法了,所以证实了虚函数是用于多态中virtual修饰父类该重写的函数,确保父类指针调用子类对象时运行子类函数的。

    2.2 、纯虚函数

        纯虚函数就像java的接口,使用了纯虚函数的类不能被实例化,定义了纯虚函数的类不用写纯虚函数的实现,由子类实现,下面看代码:

    class A  
    {  
    public:  
        virtual void printf() =0;  
    };  
    void A::printf()//纯虚函数可以不写实现  
    {  
        cout<<"printf A"<<endl;  
    }  
    class B : public A  
    {  
    public:  
        void printf(){  
            cout<<"printf B"<<endl;  
        }  
    };  
    int main(int argc, const char * argv[])  
    {  
        A *a =new A();//编译出错,纯虚函数的类不能实例化  
        a->printf();  
        return 0;  
    }  

    virtual void printf() = 0;这是虚函数的写法,我在下面写了虚函数的实现 void A::printf(),其实写不写都没关系,写了也起不了作用= 。= 。然后我才main函数中尝试吧纯虚函数的类实例化,结果直接报错,说明纯虚函数是不能实例化的。

    int main(int argc, const char * argv[])  
    {  
        A *a =newB();//这里使用了多态  
        a->printf();  
        return 0;  
    }  

    结果:

    printf B

    把main函数的a指向了子类的对象,结果可以正确打印出子类的方法。由此说明了纯虚函数也是为多态服务的,它的作用是定义一个接口,让子类去实现。

    2.3、虚基类

    虚基类是c++独有的东西,因为c++中有多继承,也是关键字virtual相关的定义。

    先来说说多继承,如果爷爷类(暂把父类的父类暂定为爷爷类= = ),父类继承自爷爷类。如果孙类继承自多个父类(听起来有点怪异),那么如果不使用虚基类,就会实例化多个爷爷类对象(越说越离奇),编译器会报错,说有歧义性。如果父类继承自虚基类,则可以解决多个父类不会实例化多个爷爷的问题,就是只有一个爷爷。

    class Grandfather{  
    public:  
        int flag;  
        Grandfather(){  
            flag = 1;  
        }  
    };  
    class Father1:publicGrandfather{  
    public:  
        Father1(){  
            flag = 2;  
        }  
    };  
    class Father2:publicGrandfather{  
    public:  
        Father2(){  
            flag = 3;  
        }  
    };  
    class Son:public Father1,publicFather2{  
    };  
    int main(int argc, const char * argv[])  
    {  
        Son *son = new Son();  
        cout<<son->flag<<endl;//这里编译错误,没法指定flag是指定那一个,歧义  
        return 0;  
    }  
    如果没有使用虚基类,多个父类继承自同一个爷爷类,就会产生歧义,到底是不是同一个爷爷?如果父类继承虚基类就不同了:
    class Grandfather{  
    public:  
        int flag;  
        Grandfather(){  
            flag = 1;  
            cout<<"Grandfather flag = "<<flag <<endl;  
        }  
    };  
    class Father1:virtualpublicGrandfather{  
    public:  
        Father1(){  
            flag = 2;  
            cout<<"Father1 flag = "<<flag<<endl;  
        }  
    };  
    class Father2:virtualpublicGrandfather{  
    public:  
        Father2(){  
            flag = 3;  
            cout<<"Father2 flag = "<<flag<<endl;  
        }  
    };  
    class Son:public Father1,publicFather2{  
    };  
    int main(int argc, const char * argv[])  
    {  
        Son *son = new Son();  
        cout<<son->flag<<endl;  
        return 0;  
    }  
    结果:

    Grandfather flag = 1

    Father1 flag = 2

    Father2 flag = 3

    3

    现在,可以运行了,class Father2:virtual public Grandfather,就是继承虚基类的写法,爷爷对象只有一个,爷爷类的变量也只实例化了一次,那为什么最后打印出来的是3呢?看构造函数的顺序就可以看出来了,现在构造了爷爷类,再构造第一个继承的父类,最后继承第二个继承的父类,因此flag最后保持在第二个父类的修改值里了。

    总的来说,虚函数 ,纯虚函数是为了多态服务,虚基类是为了只实例化一次基类存在的

    展开全文
  • C++ 虚函数 纯虚函数

    2020-02-06 15:11:20
    虚函数纯虚函数其实是两个概念,而平常我自己接触到的虚函数往往是纯虚函数,开始觉得这个概念无关紧要,后来发现还是需要认真区分为好: 首先虚函数是指在某基类中声明为 virtual 并在一个或多个派生类中被重新...
  • 虚函数纯虚函数, 虚基类,它们都和virtual有关,这三个带有虚字的定义容易使人混淆,下面先从作用上来解释这三个定义的区别:1.虚函数是用于多态中virtual修饰父类函数,确保父类指针调用子类对象时,运行子类...
  • 虚函数 (virtual) 基类:声明并定义一个虚函数 派生类:实现虚函数的...纯虚函数 (1)当想在基类中抽象出一个方法,且该基类只做能被继承,而不能被实例化; (2)这个方法必须在派生类(derived class)中被实现;
  • C++》虚函数 纯虚函数

    2020-09-11 16:32:19
    比较虚函数纯虚函数的一些区别 先上代码: #include <iostream> using namespace std; class A { public: ~A() = default; virtual void virtualFun() { cout << "A's virtualfun" << ...
  • C++虚函数纯虚函数

    2018-07-10 14:23:34
    1.虚函数(impure virtual)  C++的虚函数主要作用是“运行时多态”,父类中提供虚函数的实现,为子类提供默认的函数实现。  子类可以重写父类的虚函数实现子类的特殊化。  如下就是一个父类中的虚函数: ...
  • 感谢这些优秀的文章:虚函数纯虚函数 虚函数的实现1 虚函数的实现2 菱形继承与虚继承虚函数首先从虚函数开始说起吧.虚函数是实现了多态机制,具体表现为父类型的指针指向其子类的实例.然后通过服泪指针嗲用实际...
  • 虚函数: 所谓虚函数是指在编译时不能确定调用的是子类还是基类的... 纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加
  • c++虚函数纯虚函数是用来实现多态的重要组成部分。虚函数纯虚函数是动态绑定,而一般的函数都是静态绑定即在代码编译的时候,已经建立的绑定。    虚函数纯虚函数主要区别是,有纯虚函数的c++类,不能自己...
  • 基类class A { public: int iValue; };class B :public A { public: void bPrintf() { cout ; }; };class C :public A { public: void cPrintf() { cout << "This is class C
  • C++ 虚函数 纯虚函数

    2016-09-06 16:46:53
    一、问题多态性: 多态性分为两类:  静态多态性指在编译期间就已经确定了函数调用和函数代码直接的关系。比如,在编译重载函数和重载运算符...比如通过基类的指针或引用调用虚函数。 兼容性规则:  当我们把派生
  • 看下面两个例子虚函数纯虚函数不仅仅是在实现上有区别,两者最大的不同是:一个类中只要不含有纯虚函数,那么就可以用这个类来定义一个对象,而如果类中含有纯虚函数则不可。这两者的区别在实现装饰者模式时可以...
  • 其中抽象类指的是在类的定义中出现了纯虚函数,导致无法实例化,。 代码:头文件 #include "stdafx.h" using namespace std; class Person{ public: Person(); ~Person(); virtual void work() = 0; }; //...
  • 2:子类重写父类的虚函数 重写:返回值类型相同 函数名 参数列表 完全相同 动态多态的使用: 父类的指针或者引用 指向子类对象 #include<iostream> using namespace std; class Animal { public: //虚函数 ...
  • 首先:强调一个概念 定义一个函数为虚函数,不代表函数为不被实现的函数。 ...定义他为虚函数是为了允许用基类的指针来调用子类...定义纯虚函数是为了实现一个接口,起到一个规范的作用,规范继承这个类的程序员必须
  • c++ 虚函数 纯虚函数

    2013-07-05 11:04:43
    虚函数的调用原理 多态性给我们带来了好处:多态使得我们可以通过基类的引用或指针来指明一个对象(包含其派生类的对象),当调用函数时可以自动判断调用的是哪个对象的函数。 一个函数说明为虚函数,...
  • 虚函数纯虚函数(抽象类) 1.虚函数意在实现多态时,让基类指针能够根据引用的实际指向的指针类型,判断并调用相应方法。 派生类重写虚函数的函数也被编译器自动添加上virtual,所以为了清晰,请手动标注virtual ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,817
精华内容 1,926
关键字:

虚函数纯虚函数