精华内容
下载资源
问答
  • 对C++虚函数理解

    2018-09-18 21:46:59
    以前只知道虚函数是由一个叫作“虚函数表”的东西实现,但是一直不知道具体是怎么实现,今天看到csdn学院上c++虚函数的原理时,有几个问题,还是不怎么清楚,只好做一些测试,具体让我产生疑问的截图如下: ...

    以前只知道虚函数是由一个叫作“虚函数表”的东西实现,但是一直不知道具体是怎么实现,今天看到csdn学院上c++虚函数的原理时,有几个问题,还是不怎么清楚,只好做一些测试,具体让我产生疑问的截图如下:

     

    从上面的截图里,主要有2个问题

    1.按上图所说,编译器会往类中插入“指向虚函数表的指针(__vfptr)”,那么如果这个类所生成几个不同的对象,这几个对象的__vfptr都相同吗?

    2.子类和父类是共用一个虚函数表吗?

     

    关于这两个问题,我写了一个程序来验证

    #include "stdio.h"
    class Animal
    {
    public:
        virtual void  eat()
        {
            printf("animal  eat\n");
        }
        virtual void crazy()
        {
            printf("animal  crazy\n");
        }
    };
    
    class Cat :public Animal
    {
    };
    class WhiteCat :public Cat
    {
    public:
        void crazy()
        {
            printf("WhiteCat crazy\n");
        }
    };
    void main()
    {
        Animal animal1;
        Animal animal2;
    
        printf("animal1 __vfptr:%X\n",animal1);    
        printf("animal2 __vfptr:%X\n", animal2);
    
        Cat   cat1;
        Cat   cat2;
        printf("cat1 __vfptr:%X\n",cat1 );
        printf("cat2 __vfptr:%X\n",cat2);
        
        WhiteCat whiteCat1;
        WhiteCat whiteCat2;
        printf("whiteCat1 __vfptr:%X\n", whiteCat1);
        printf("whiteCat1 __vfptr:%X\n", whiteCat2);
    
        getchar();
    }

     

    在getchar()函数下一个断点启动调试,此时程序运行如下

    1可以看见animal1和animal2的__vfptr是一样的,同样cat1和cat2,whitecat1和whitecat2也是如此,但是cat和animal的__vfptr却并不相同

    分析:(1)animal1和animal2都是Animal类生成的实例,他们指向了同一个虚函数表,同理cat1和cat2,whitecat1和whitecat2也是如此

               (2)尽管Cat是从Animal派生,并且Cat也没有改写基类的虚函数,但是该类生成的实例所对应的__vfptr却与基类不一样,这也就意味着基类和派生类并没有共用一个虚函数表

     

     

    下面继续分析,虚函数表是怎么实现的,

    (1)在vs里,点击右键---转到反汇编

     

    (2)在汇编界面地址栏里输入0xDB7B34(animal1和animal2的__vfptr指向的地址),并回车

    (3)我们可以看到animal1和animal2的__vfptr指向的地址存储了7C 11 DB 00 4F 11 DB 00 00 00 00 00 ...等字节,我们知道__vfptr是指向虚函数表的,而虚函数表可以看成是函数指针数组(存储函数指针的数组),我们先取前4个字节看看到底是不是指向函数指针,前4个字节是7C 11 DB 00,因为x86结构是属于“小端”架构(低字节在低位,高字节在高位),所以这4个字节对应的函数指针是00DB117C,此时我们在汇编界面的地址栏输入0xDB117C,并回车,如下图所示

    (4)很明显0xDB117C存储的是一段汇编代码 jmp  Animal::eat,了解汇编代码的人都知道,该指令是无条件跳转指令,直接跳转到Animal::eat的汇编代码段

    用同样的方法测试下4个字节4F 11 DB 00

    接下来的 00 00 00 00 这4个字节,是虚函数表的结尾标志。

    大家也可以用同样的方法查看派生类的虚函数表。。。

    至此,我们终于得见虚函数表的真实面目啦,也许有人会问这个虚函数表好像跟想象的不一样,虚函数表不是存储虚函数地址的吗,这里怎么会是jmp指令,虽然最终可以通过这个jmp指令转到虚函数地址,但是他终究不是虚函数地址呀,难道书上面说错了吗?(答:书上没有说错,因为这是debug调试版本,在debug调试版本里是会出现jmp指令的,但release版本就不是jmp指令了,具体debug版本为什么要有jmp,为什么要多此一举,就下次再说吧)

     

     

     

     

     

    展开全文
  • //虚函数怎么实现的 //虚函数的说明 //虚析构函数 //构造函数和析构函数的调用顺序 //纯虚函数与抽象类 //为什么要引用抽象基类和纯虚函数 //虚函数与纯虚函数的区别 什么是多态 多态性是指发出的消息被...

    //什么是多态
    //实现多态性的方式
    //虚函数是怎么实现的
    //虚函数的说明
    //虚析构函数
    //构造函数和析构函数的调用顺序
    //纯虚函数与抽象类
    //为什么要引用抽象基类和纯虚函数
    //虚函数与纯虚函数的区别

    什么是多态

    多态性是指发出的消息被不同的对象接收时会产生完全不同的行为
    (同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果)


    实现多态性的方式

    <1>运算符重载和函数重载
    静态关联:关联工作在编译、链接阶段完成,在此期间,系统就可以根据函数的参数类型和参数个数决定调用哪个同名函数。
    静态关联的优缺点:程序执行效率高,但对程序员水平要求较高

    <2>虚函数和纯虚函数
    动态关联:关联工作在程序运行阶段完成。
    动态关联的优缺点:提供更好的编程灵活性、问题抽象性和程序的易维护性,但是函数调用速度慢


    虚函数是怎么实现的(通过虚函数表实现)

    <1>定义:

    virtual    函数类型    函数名(参数表)
        {
            函数体;
        }

    <2>如何利用虚函数实现运行时的多态
    记住,通过对象调用虚函数不会出现多态(通过指针或者引用才会有多态性)
    在构造函数里面调用虚函数不会出现多态,指定命名域调用不会出现多态

    虚函数的说明

    <1>派生类应该从它的基类公有派生。一个虚函数无论被公有继承多少次,它仍然保持虚函数的特性
    <2>必须首先在基类中定义虚函数。应该在需要具有动态多态性的最高层内首先声明虚函数
    <3>在派生类中对基类声明的虚函数进行重定义时,关键字virtual可写可不写,但在容易引起混乱的情况下,建议加上virtual
    <4>只有通过基类指针或者基类引用访问虚函数时才能获得运行时的多态性
    <5>虚函数必须是其所在类的成员函数,而不能是友元函数,更不能是静态成员函数,因为虚函数调用要靠特定对象来激活对应的函数
    <6>内联函数不能使虚函数,因为内联函数时不能在运行时动态确定其位置的


    虚析构函数(为什么我们不提虚构造函数呢?)

    virtual ~类名(){}

    只有析构函数可以被声明为虚函数,构造函数不能声明为虚函数!!!
    虚函数是根据不同类型的对象产生不同的动作,构造函数是在对象生成之前调用的,如果对象还没有产生,那么虚构造函数也就没什么意义
    如果一个类的析构函数时虚函数,那么由它派生而来的所有派生类的析构函数,不管是否用virtual进行说明,也都是虚析构函数。保证使用时基类类型的指针能够调用适当的析构函数针对不同的对象进行清理工作


    构造函数和析构函数的调用顺序(包含多重继承、类中包含对象成员)

    构造函数顺序:首先调用基类的构造函数(先调用哪个基类 与 派生类继承基类的顺序一致)
    (若为菱形结构,则基虚类构造函数只被调用一次)
    其次调用类的对象成员的构造函数(先调用哪个对象成员的构造函数 与 对象成员的定义顺序一致)
    最后调用派生类的构造函数

    析构函数的调用顺序与构造函数相反


    纯虚函数与抽象类

    包含纯虚函数的类被称为抽象类

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

    纯虚函数的作用是在基类中为派生类保留一个函数的名字,以便派生类根据需要对它进行定义。


    为什么要引用抽象基类和纯虚函数

    <1>为了方便使用多态性
    <2>在很多情况下,基类本身生成对象是不合理的。例如:动物作为一个基类可以派生出老虎、狮子等子类,但动物本身生成对象明显不合常理。抽象基类不能够被实例化,它定义的纯虚函数相当于接口,能把派生类的共同行为提取出来。


    虚函数与纯虚函数的区别

    <1>虚函数是实现的,哪怕是空实现;纯虚函数只是一个接口,是函数声明,需要子类去实现
    <2>虚函数在子类中也可以不修改;但纯虚函数必须在子类中实现
    <3>虚函数的类用于“实作继承”,也就是说继承接口的同时也继承了父类的实现,当然也可以完成自己的实现;纯虚函数的类用于“介面继承”,即纯虚函数关注的是接口统一性,实现由子类完成
    <4>带纯虚函数的类叫虚基类(抽象类),这种类不能直接实例化对象,只有被继承,并实现其纯虚函数后,才能使用

    展开全文
  • 理解的C++虚函数

    2019-09-30 18:48:00
    今天拜读了陈皓的C++ 虚函数表解析的文章,感觉对C++的继承和多态又有了点认识,这里写下自己的理解。如果哪里不对的,欢迎指正。如果对于C++虚函数表还没了解的话,请先拜读下陈皓的C++ 虚函数表解析的文章,不然我...

    今天拜读了陈皓的C++ 虚函数表解析的文章,感觉对C++的继承和多态又有了点认识,这里写下自己的理解。如果哪里不对的,欢迎指正。如果对于C++虚函数表还没了解的话,请先拜读下陈皓的C++ 虚函数表解析的文章,不然我写的可能你看不懂。

    以前一直对于c++多态感觉很神奇,从书上看,多态就是在构造子类对象的时候,通过虚函数,利用父类指针,来调用子类真正的函数。这个解释是正确的,但是它是怎么实现的呢,一直再猜想。以前也知道有虚函数表这件事,也没有仔细理解是什么东东。今天仔细读了陈皓的文章,才明白C++多态的原理。这里说说我的理解:

     先附上我写的一段简单代码:

      1 #include <iostream>
      2 using namespace std;
      3 
      4 class Base{
      5 public:
      6     virtual void f() { cout << "Base::f()" << endl;}
      7     virtual void g() { cout << "Base::g()" << endl;}
      8 };
      9 class Derive : public Base {
     10 public:
     11     virtual void f() { cout << "Devive::f()" << endl;}
     12     virtual void f1() { cout << "Devive::f1()" << endl;}
     13     virtual void g1() { cout << "Devive::g1()" << endl;}
     14 };
     15 typedef void (*Fun)(void);
     16 
     17 int main()
     18 {
     19     Fun pFun = NULL;
     20 
     21     Base b;
     22     cout << "virtual table address: " << (int*)(&b) << endl;
     23     cout << "first virtual function address: " << (int*)*(int*)(&b) << endl;
     24     pFun = (Fun)(*(int*)*(int*)(&b));
     25     pFun();
     26     pFun = (Fun)*((int*)*(int*)(&b)+1);
     27     pFun();
     28 
     29     cout << "*********" << endl;
     30 
     31     Derive d;
     32     cout << "virtual table address: " << (int*)(&d) << endl;
     33     cout << "first virtual function address: " << (int*)*(int*)(&d) << endl;
     34     pFun = (Fun)(*(int*)*(int*)(&d));
     35     pFun();
     36     pFun = (Fun)*((int*)*(int*)(&d)+1);
     37     pFun();
     38     pFun = (Fun)*((int*)*(int*)(&d)+2);
     39     pFun();
     40     pFun = (Fun)*((int*)*(int*)(&d)+3);
     41     pFun();
     42 

     

     输出结果:

    virtual table address: 0xbfd268f8
    first virtual function address: 0x8048b90
    Base::f()
    Base::g()
    *********
    virtual table address: 0xbfd268f4
    first virtual function address: 0x8048b78
    Devive::f()
    Base::g()
    Devive::f1()
    Devive::g1()

    理解1:首先你想要实现多态就必须通过虚函数,如果第6行我们改为 void f() { cout << "f" << endl;}, 那么顾名思义这个f()函 数就不会进入虚函数表中,也就没有多态之说了

     

    理解2:在32位系统和64位系统下,取得虚函数表里的函数的方法还有所不同,再32位系统下,如程序那样取就行,而在64位系统下,取得第二个函数(Fun)*((int*)*(int*)(&d+2),第三个函数(Fun)*((int*)*(int*)(&d+4)....

     

    理解3:对于程序清单里,我们分别输出类 Base和类Derive的v-table的地址和第一个虚函数的地址,我们发现,他们地址根本不一样,所以说,C++会为每一个类都分配一个virtual table

     

    理解4:如果我们分别打印 *(int*)*(int*)(&b),*(int*)*(int*)(&d),我们发现他们的值都是一样的,这就验证我的猜想,虚函数表存放都是虚函数的指针(这话说的有点蛋疼,但这不是关键),故子类调用父类的时候,调用函数,是去查的虚函数表,然后查到函数的真正的位置,然后调用

     

    理解5:在理解了虚函数表的结构后,我觉得多态的函数调用,是跟子类的虚函数表有关的,可以说是跟子类没有直接关系的(我以前觉得多态函数的调用是先去父类的函数中找这个函数,然后在这个子类中找同样的函数调用它,现在想来真是2到渣的节奏)

    附几张图,来说明这个调用关系

    说明一下,父类a的函数分别是virtual void f(),virtual void g(),virtual void h()

         子类b的函数分别是virtual void f1(), virtual void g1(), virtual void h1()

         子类c的函数分别是virtual void f(), virtual void g1(), virtual void h1()

    类a.只有父类时

     

    类b.有子类继承,但是没有函数的重载

     

    类c.有子类继承,有函数重载

     

    如:我们调用

    Derive c;

    Base *p_base = &c;

    p_base->f();

    这里的调用过程是,在类C虚函数表中查找到Base类的f()的地址【虚函数表内函数的存放顺序是,先放父类的虚函数,然后再存放子类的虚函数】,然后在该地址处取得存放的真正的函的地址,即是子类的函数,故调用的是子类的函数

     版权所有,如要转载请说明出处及作者

    转载于:https://www.cnblogs.com/457220157-FTD/p/4011214.html

    展开全文
  • 下面是对C++的虚函数这玩意儿的理解。一, 什么是虚函数(如果不知道虚函数为何物,但有急切的想知道,那你就应该从这里开始)简单地说,那些被virtual关键字修饰的成员函数,就是虚函数虚函数的作用,用专业术语来...

    虚函数联系到多态,多态联系到继承。所以本文中都是在继承层次上做文章。没了继承,什么都没得谈。

    下面是对C++的虚函数这玩意儿的理解。

    一, 什么是虚函数(如果不知道虚函数为何物,但有急切的想知道,那你就应该从这里开始)

    简单地说,那些被virtual关键字修饰的成员函数,就是虚函数。虚函数的作用,用专业术语来解释就是实现多态性(Polymorphism),多态性是将接口与实现进行分离;用形象的语言来解释就是实现以共同的方法,但因个体差异而采用不同的策略。下面来看一段简单的代码

    class A{

    public:

    void print(){ cout<

    };

    class B:public A{

    public:

    void print(){ cout<

    };

    int main(){ //为了在以后便于区分,我这段main()代码叫做main1

    A a;

    B b;

    a.print();

    b.print();

    }

    通过class A和class B的print()这个接口,可以看出这两个class因个体的差异而采用了不同的策略,输出的结果也是我们预料中的,分别是This is A和This is B。但这是否真正做到了多态性呢?No,多态还有个关键之处就是一切用指向基类的指针或引用来操作对象。那现在就把main()处的代码改一改。

    int main(){ //main2

    A a;

    B b;

    A* p1=&a;

    A* p2=&b;

    p1->print();

    p2->print();

    }

    运行一下看看结果,哟呵,蓦然回首,结果却是两个This is A。问题来了,p2明明指向的是class B的对象但却是调用的class A的print()函数,这不是我们所期望的结果,那么解决这个问题就需要用到虚函数

    class A{

    public:

    virtual void print(){ cout<

    };

    class B:public A{

    public:

    void print(){ cout<

    };

    毫无疑问,class A的成员函数print()已经成了虚函数,那么class B的print()成了虚函数了吗?回答是Yes,我们只需在把基类的成员函数设为virtual,其派生类的相应的函数也会自动变为虚函数。所以,class B的print()也成了虚函数。那么对于在派生类的相应函数前是否需要用virtual关键字修饰,那就是你自己的问题了。

    现在重新运行main2的代码,这样输出的结果就是This is A和This is B了。

    现在来消化一下,我作个简单的总结,指向基类的指针在操作它的多态类对象时,会根据不同的类对象,调用其相应的函数,这个函数就是虚函数。

    首先:强调一个概念

    定义一个函数为虚函数,不代表函数为不被实现的函数。

    定义他为虚函数是为了允许用基类的指针来调用子类的这个函数。

    定义一个函数为纯虚函数,才代表函数没有被实现。

    定义纯虚函数是为了实现一个接口,起到一个规范的作用,规范继承这个类的程序员必须实现这个函数。

    1、简介

    假设我们有下面的类层次:

    class A

    {

    public:

    virtual void foo()

    {

    cout<

    }

    };

    class B:public A

    {

    public:

    void foo()

    {

    cout<

    }

    };

    int main(void)

    {

    A *a = new B();

    a->foo(); // 在这里,a虽然是指向A的指针,但是被调用的函数(foo)却是B的!

    return 0;

    }

    这个例子是虚函数的一个典型应用,通过这个例子,也许你就对虚函数有了一些概念。它虚就虚在所谓“推迟联编”或者“动态联编”上,一个类函数的调用并不是在编译时刻被确定的,而是在运行时刻被确定的。由于编写代码的时候并不能确定被调用的是基类的函数还是哪个派生类的函数,所以被成为“虚”函数。

    虚函数只能借助于指针或者引用来达到多态的效果。

    C++纯虚函数

    一、定义

    纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加“=0”

    virtual void funtion1()=0

    二、引入原因

    1、为了方便使用多态特性,我们常常需要在基类中定义虚拟函数。

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

    为了解决上述问题,引入了纯虚函数的概念,将函数定义为纯虚函数(方法:virtual ReturnType Function()= 0;),则编译器要求在派生类中必须予以重写以实现多态性。同时含有纯虚拟函数的类称为抽象类,它不能生成对象。这样就很好地解决了上述两个问题。

    声明了纯虚函数的类是一个抽象类。所以,用户不能创建类的实例,只能创建它的派生类的实例。

    纯虚函数最显著的特征是:它们必须在继承类中重新声明函数(不要后面的=0,否则该派生类也不能实例化),而且它们在抽象类中往往没有定义。

    定义纯虚函数的目的在于,使派生类仅仅只是继承函数的接口。

    纯虚函数的意义,让所有的类对象(主要是派生类对象)都可以执行纯虚函数的动作,但类无法为纯虚函数提供一个合理的缺省实现。所以类纯虚函数的声明就是在告诉子类的设计者,“你必须提供一个纯虚函数的实现,但我不知道你会怎样实现它”。

    抽象类的介绍

    抽象类是一种特殊的类,它是为了抽象和设计的目的为建立的,它处于继承层次结构的较上层。

    (1)抽象类的定义: 称带有纯虚函数的类为抽象类。

    (2)抽象类的作用:

    抽象类的主要作用是将有关的操作作为结果接口组织在一个继承层次结构中,由它来为派生类提供一个公共的根,派生类将具体实现在其基类中作为接口的操作。所以派生类实际上刻画了一组子类的操作接口的通用语义,这些语义也传给子类,子类可以具体实现这些语义,也可以再将这些语义传给自己的子类。

    (3)使用抽象类时注意:

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

    • 抽象类是不能定义对象的。

    总结:

    1、纯虚函数声明如下: virtual void funtion1()=0; 纯虚函数一定没有定义,纯虚函数用来规范派生类的行为,即接口。包含纯虚函数的类是抽象类,抽象类不能定义实例,但可以声明指向实现该抽象类的具体类的指针或引用。

    2、虚函数声明如下:virtual ReturnType FunctionName(Parameter);虚函数必须实现,如果不实现,编译器将报错,错误提示为:

    error LNK****: unresolved external symbol "public: virtual void __thiscall ClassName::virtualFunctionName(void)"

    3、对于虚函数来说,父类和子类都有各自的版本。由多态方式调用的时候动态绑定。

    4、实现了纯虚函数的子类,该纯虚函数在子类中就编程了虚函数,子类的子类即孙子类可以覆盖该虚函数,由多态方式调用的时候动态绑定。

    5、虚函数是C++中用于实现多态(polymorphism)的机制。核心理念就是通过基类访问派生类定义的函数。

    6、在有动态分配堆上内存的时候,析构函数必须是虚函数,但没有必要是纯虚的。

    7、友元不是成员函数,只有成员函数才可以是虚拟的,因此友元不能是虚拟函数。但可以通过让友元函数调用虚拟成员函数来解决友元的虚拟问题。

    8、析构函数应当是虚函数,将调用相应对象类型的析构函数,因此,如果指针指向的是子类对象,将调用子类的析构函数,然后自动调用基类的析构函数。

    有纯虚函数的类是抽象类,不能生成对象,只能派生。他派生的类的纯虚函数没有被改写,那么,它的派生类还是个抽象类。

    定义纯虚函数就是为了让基类不可实例化化

    因为实例化这样的抽象数据结构本身并没有意义。

    或者给出实现也没有意义

    实际上我个人认为纯虚函数的引入,是出于两个目的

    1、为了安全,因为避免任何需要明确但是因为不小心而导致的未知的结果,提醒子类去做应做的实现。

    2、为了效率,不是程序执行的效率,而是为了编码的效率。

    展开全文
  • Class A { ...当程序编译链接(compile time)后,根据虚函数的原则,main函数中不是已经注定要执行B::print()函数了吗? run time是什么意思呢?不就是执行main函数的代码吗? 我所不理解的地方在哪?
  • 我们都知道代码运行时各个系统会...但是当有继承发生时,函数调用方式是怎么样的呢?本篇内容就让我们一起来看一下:普通函数的调用方式:假设这里有一个很简单的类Base我们实例化出来一个类(Base b)然后在vs里用调...
  • 我们都知道代码运行时...但是当有继承发生时,函数调用方式是怎么样的呢?本篇内容就让我们一起来看一下:普通函数的调用方式:假设这里有一个很简单的类Base我们实例化出来一个类(Base b)然后在vs里用调试模式看一...
  • 我们都知道代码运行时各个系统会...但是当有继承发生时,函数调用方式是怎么样的呢?本篇内容就让我们一起来看一下:普通函数的调用方式:假设这里有一个很简单的类Base我们实例化出来一个类(Base b)然后在vs里用调...
  • 我们都知道代码运行时各个系统会为...但是当有继承发生时,函数调用方式是怎么样的呢? 本篇内容就让我们一起来看一下: 普通函数的调用方式: 假设这里有一个很简单的类Base 我们实例化出来一个类(Ba...
  • C++多态虚函数列表

    2020-08-18 10:45:48
    虚函数怎么通过虚函数类表实现的呢 可以理解为当一个类中存设有虚函数的时候,在创建这个对象的时候系统会就创建一个虚函数指针,指向虚函数类表。虚函数类表中可以理解为一个单独的空间,专门为对象存放虚函数的。 ...
  • 如果声明了某个成员为虚函数。则在该类中不能出现和这个成员函数同名并且返回值、参数个数、类型都相同的非虚函数。 上面的都能明白,关键是下面这段话: ...在子类中不定义一个同名函数怎么实现多态性啊?
  • 下面是对C++的虚函数这玩意儿的理解。一, 什么是虚函数(如果不知道虚函数为何物,但有急切的想知道,那你就应该从这里开始)简单地说,那些被virtual关键字修饰的成员函数,就是虚函数虚函数的作用,用专业术语...
  • 虚函数

    2010-03-10 14:54:00
    //今天深刻理解虚函数和纯虚函数的作用和用法 //如果子类实现了虚函数则调用子类的方法, //如果子类没有实现该函数则调用父类的方法。 //究竟怎么用呢: 假如CChild 派生自 CMan ,有个虚函数 Eat();CMan m_...
  • 我们都知道代码运行时...但是当有继承发生时,函数调用方式是怎么样的呢?本篇内容就让我们一起来看一下:普通函数的调用方式:假设这里有一个很简单的类Base我们实例化出来一个类(Base b)然后在vs里用调试模式看一...
  • 虚函数声明方式后加一个“=0”,并且不提供实现。抽象类不允许实例化(这样做编译器会报错,因为有成员函数没有实现,编译器不知道怎么调用)。纯虚函数的实现机制和虚函数类似,只是要求派生类类必须自己实现一个...
  • 什么是虚函数

    2018-02-12 10:44:16
    下面是对C++的虚函数这玩意儿的理解。 一, 什么是虚函数(如果不知道虚函数为何物,但有急切的想知道,那你就应该从这里开始) 简单地说,那些被virtual关键字修饰的成员函数,就是虚函数虚函数的作用,用专业...
  • 今天被一个问题困扰了一下,当我们定义了一个类,然后在让一个子类去继承这个类,定义子类和父类都写好构造函数和析构函数,实例化这个子类对象时,会先调用父类的构造函数,在调用子类的构造函数,释放这个对象的...
  • 虚函数学习

    2016-08-15 11:18:13
    最近参加几次笔试都考到了虚函数,但是这个东西我并不怎么理解。偶然间在网上看到这篇写得不错的东西,所以在学习之余转回来和大家共享。谢谢作者的工作。   一.简介  虚函数是C++中用于实现多态...
  • 1、虚函数是动态绑定,与多态相关,所以需要知道对象的类型,如果没有构造出对象怎么知道对象的类型,怎么执行虚函数; 2、虚函数实现多态,最后只执行一个函数,而构造函数需要执行从基类到子类的各个构造函数,...
  • 上一个博客写的是析构函数 从析构函数我们就可以知道了我们写c++程序的时候析构函数最好是写成虚函数,因为这样的话,释放空间的时候,会把父类 以及子类的空间都是释放了 ,然后今天我们 看的是析构函数,假如是...
  • 虚函数-运行时多态的理解

    千次阅读 2016-03-16 09:20:29
    现在我们来讨论在这三个类中的绘制自己的函数都应该怎么实现。在形状中嘛,什么也不做就行了。在多边形中嘛,只要把它所有的顶点首尾相连起来就行了。在圆形中嘛,依据它的圆心和它的半径画一个360度的圆弧就行了。 ...
  • 下面是对C++的虚函数这玩意儿的理解。 一, 什么是虚函数(如果不知道虚函数为何物,但有急切的想知道,那你就应该从这里开始) 简单地说,那些被virtual关键字修饰的成员函数,就是虚函数虚函数的作用,用专业...
  •  这个问题是C++理解虚函数和动态绑定的一个基础,也是面试常考的一个点。虽然几乎每本书中都会提及这个点,但是很少有把其具体阐明。本文通过具体实例+理论阐述尽量清晰解释这个问题。  首先看一下effective c++...
  • 下面是对C++的虚函数这玩意儿的理解。一, 什么是虚函数(如果不知道虚函数为何物,但有急切的想知道,那你就应该从这里开始)简单地说,那些被virtual关键字修饰的成员函数,就是虚函数虚函数的作用,用专业术语...

空空如也

空空如也

1 2 3 4 5 ... 8
收藏数 148
精华内容 59
关键字:

虚函数怎么理解