精华内容
下载资源
问答
  • override:对虚函数进行重写的函数 final与override 假设声明一个基类的指针,它可以根据指向的对象类型动态的绑定对应的函数 虚函数的默认实参 如果我们通过基类的引用或指针调用函数,则使用基类中定义的默认实参 ...

    虚函数 (virtual)

    基类:声明并定义一个虚函数

    派生类:实现虚函数的重写与覆盖

    final:后续派生类不能再覆盖的虚函数
    override:对虚函数进行重写的函数

    final与override

    假设声明一个基类的指针,它可以根据指向的对象类型动态的绑定对应的函数

    虚函数的默认实参

    如果我们通过基类的引用或指针调用函数,则使用基类中定义的默认实参

    纯虚函数

    (1)当想在基类中抽象出一个方法,且该基类只做能被继承,而不能被实例化;
    (2)这个方法必须在派生类(derived class)中被实现;
       如果满足以上两点,可以考虑将该方法申明为纯虚函数
    

    class CShape
    {
    public:
    virtual void Show()=0;
    };

    抽象基类

    含有纯虚函数的类为虚基类;
    虚基类不能实例化
    
    展开全文
  • 虚函数的使用

    2021-05-05 23:02:20
    当把基类的某个成员函数声明为虚函数后,允许在其派生类中该函数重新定义,赋予它新的功能,并且可以通过指向基类的指针指向同一类族中不同类的对象,从而调用其中的同名函数。 在基类用virtual声明成员函数为...

    当把基类的某个成员函数声明为虚函数后,允许在其派生类中对该函数重新定义,赋予它新的功能,并且可以通过指向基类的指针指向同一类族中不同类的对象,从而调用其中的同名函数。

    • 在基类用virtual声明成员函数为虚函数。
      这样就可以在派生类中重新定义此函数,为它赋予新的功能,并能方便地被调用。在类外定义虚函数时,不必再加virtual。
    • 在派生类中重新定义此函数,要求函数名、函数类型、函数参数个数和类型全部与基类的虚函数相同,并根据派生类的需要重新定义函数体。
      C++规定,当一个成员函数被声明为虚函数后,其派生类中的同名函数都自动成为虚函数。因此在派生类重新声明该虚函数时,可以加virtual,也可以不加,但习惯上一般在每一层声明该函数时都加virtual,使程序更加清晰。如果在派生类中没有对基类的虚函数重新定义,则派生类简单地继承其直接基类的虚函数。
    • 定义一个指向基类对象的指针变量,并使它指向同一类族中需要调用该函数的对象。
    • 通过该指针变量调用此虚函数,此时调用的就是指针变量指向的对象的同名函数
    展开全文
  • 对虚函数的理解

    2013-04-14 19:47:11
     虚函数是动态绑定,也就是说,使用指向派生对象的基类指针和引用调用一个virtual函数时,究竟调用哪一份函数实现代码,取决于发出调用的那个对象的动态类型。  简而言之就是用父类指针或引用 指向 其子类...

     1.     

         从基类指针或基类引用获得派生类的行为的最好方法是通过虚函数机制。

         虚函数是动态绑定的,也就是说,使用指向派生对象的基类指针和引用调用一个virtual函数时,究竟调用哪一份函数实现代码,取决于发出调用的那个对象的动态类型。

        简而言之就是用父类的指针或引用 指向 其子类的实例,然后通过父类的指针调用实际子类的成员函数。这种技术可以让父类的指针有“多种形态”。

        

    2. 构造函数不能是虚函数,另外,析构函数允许为虚并且往往是必要的。

         在构造函数或析构函数中调用虚函数,实际执行的是该类的对应函数,而不是子类的对应函数,因为子类非基类的部分还没有构造好,多态是被disable的。 

     

    3.虚函数的实现原理:

           编译器会为每个含有虚函数的类添加一个隐藏的数据成员即虚函数表指针(vptr),在构造函数内插入隐藏的将虚函数表指针初始化为虚函数首地址的代码,创建一个虚函数表(vtble)。

           一般虚函数表指针放在对象首地址的前4字节处,大部分编译器都是这样做的,这主要是为了保证取到虚函数表的有最高性能。
    虚函数表将被该类的所有对象共享。而且对于虚函数表,实质上是一块连续的内存,每4字节的内存单元存放了一个虚函数的入口地址,而虚函数的地址的排列顺序是依据虚函数在类中的声明顺序而定的。
           在实例化含有虚函数的类对象时,会调用构造函数完成虚函数表指针的初始化。在虚函数被调用时,
    通过vptr间接访问vtble,在vtble中找到对应的虚函数地址并调用执行。

     

    4.虚函数表

       虚函数表放在定义这个虚函数的导出类的模块的常量段中。一个含有虚函数的类只有一个虚函数表,也就是说从该类实例化出来的对象共享一个虚函数表

       

    5. 虚函数地址的获取

    由于虚表指针存放在类对象的前4个字节中,我们首先需要将类对象的首地址转化成int型指针,并通过这个int型指针获得前4个字节的内容,这个内容就是虚表的地址。接着我们将这个虚表的地址再转化成int型指针,并通过这个int型指针获得虚表的前4个字节的内容,这个内容就是虚表的第一项的值,也就是第一个虚函数的地址。

     

    //假设虚函数指针类型为Fun;

     

    Derieved d;

    (int*)(&d)             取vptr的地址
    *(int*)(&d)            取vptr的值,即vtble的地址
    (int*)*(int*)(&d)    取vtble的值,即vtble首元素的地址,注:vtble是一个虚函数指针数组
    (Fun)*((int*)*(int*)(&d) +0)      取vtbl数组的第一个元素的值,即Derived中第一个虚函数的地址
     (Fun)*((int*)*(int*)(&d) +1)     取vtbl数组的第二个元素的值

    或者

    *(Fun*)((int*)*(int*)(&d) +0)    取vtbl数组的第一个元素,即Derived中第一个虚函数的地址

    *(Fun*)((int*)*(int*)(&d) +1)    取vtbl数组的第二个元素


    6.

    #include <iostream>

    using namespace std;

    class B   
    {    
    public:    
        virtual void fun()      
        {     
            cout << "base fun called";     
        };    
    };  

    class D : public B    
    {    
    private:   
        virtual void fun()      
        {     
            cout << "driver fun called";    
        };    
    };  

    int main(int argc, char* argv[])   
    {       
        B* p = new D();    
        p->fun();    
        return 0;    
    }  
    运行时会输出 driver fun called

    从这个实验,可以更深入的了解虚拟函数编译时的一些特征:
    在编译虚拟函数调用的时候,例如p->fun(); 只是按其静态类型来处理的, 在这里p的类型就是B,不会考虑其实际指向的类型(动态类型)。
        也就是说,碰到p->fun();编译器就当作调用B的fun来进行相应的检查和处理。
    因为在B里fun是public的,所以这里在“访问控制检查”这一关就完全可以通过了。
    然后就会转换成(*p->vptr[1])(p)这样的方式处理, p实际指向的动态类型是D,
        所以p作为参数传给fun后(类的非静态成员函数都会编译加一个指针参数,指向调用该函数的对象,我们平常用的this就是该指针的值), 实际运行时p->vptr[1]则获取到的是D::fun()的地址,也就调用了该函数, 这也就是动态运行的机理。


    为了进一步的实验,可以将B里的fun改为private的,D里的改为public的,则编译就会出错。
    C++的注意条款中有一条" 绝不重新定义继承而来的缺省参数值" 
    (Effective C++ Item37, never redefine a function's inherited default parameter value) 也是同样的道理。

    展开全文
  • c++ 虚函数_c++ 虚函数

    2020-11-28 09:21:46
    会根据不同对象调用其相应函数,这个函数就是虚函数,虚函数使用virtual修饰函数名,虚函数作用是在程序运行阶段动态地选择合适成员函数,在定义了虚函数后,可以在基类的派生类中对虚函数进行重新定义...

    指向基类的指针在操作它的多态类对象时,会根据不同的类对象调用其相应的函数,这个函数就是虚函数,虚函数使用virtual修饰函数名,虚函数的作用是在程序的运行阶段动态地选择合适的成员函数,在定义了虚函数后,可以在基类的派生类中对虚函数进行重新定义,在派生类中重新定义的函数应与虚函数具有相同的参数个数和形参类型,以实现统一的接口,如果在派生类中没有对虚函数重新定义,则它继承其基类的虚函数。

    在使用虚函数时要注意以下几个方面:

    a.只需要在声明函数的类体中使用关键字virtual将函数声明为虚函数,而定义函数时不需要使用关键字virtual.

    b.当将基类中的某一个成员函数声明为虚函数后,派生类中的同名函数自动成为虚函数

    c.如果声明了某个成员函数为虚函数,则在该类中不能再出现与这个成员函数同名并返回值,参数个数,类型都相同的非虚函数。在以该类为基类的派生类中,也不能出现这种同名函数

    d.非类的成员函数不能定义为虚函数,全局函数以及类的成员函数中静态成员函数和构造函数也不能定义为虚函数,但可以将析构函数定义为虚函数,将基类的析构函数定义为虚函数后,当利用delete删除一个指向派生类定义的对象指针时,系统会调用相应的类的析构函数,而不将析构函数定义为虚函数时,只调用基类的析构函数。

    e.普通派生类对象,先调用基类构造函数再调用派生类构造函数

    f.基类的析构函数应该定义为虚函数,这样可以在实现多态的时候不造成内存泄露。基类析构函数未声明virtual,基类指针指向派生类时,delete指针不调用派生类析构函数,有virtual则先调用派生类析构函数再调用基类析构函数。

    g.基类指针动态建立派生类对象,普通调用派生类构造函数

    h.指针声明不调用构造函数

    d56d017c60e03810c20805fc8cd3e240.png
    展开全文
  • 虚函数的应用

    2020-02-28 00:51:42
    因为当我们使用基类的引用或指针调用基类中定义的某个函数时,我们并不知道该函数真正的对象是什么类型(属于哪个类),因为它可能是一个基类的对象,也可能是一个子类的对象 下面一个例子进行举例: ...
  • 调用虚函数时编译器需要动态绑定以确定究竟要调用的是哪一个类的函数,而触发动态绑定的不仅要求调用的函数是虚函数,还要求必须通过基类类型的引用或指针进行函数调用。 (1)派生类对象可以当做基类对象使用 ...
  • 虚函数

    2018-07-27 14:33:23
    虚函数实现的动态多态性就是:同一类族中不同类的对象同一函数调用作出不同的响应。 虚函数使用方法: 在基类中用virtual声明成员函数为虚函数。 //在类外定义虚函数时,不必再加virtual 在派生类中重新...
  • C++虚函数基类一个成员函数,您可以在派生类中重新定义它。 它声明使用virtual关键字。它用于告诉编译器函数执行动态链接或后期绑定。后期绑定或动态链接在后期绑定函数调用在运行时被解决。 因此,编译器在...
  • C++虚函数

    2016-04-29 22:04:39
    虚函数 虚函数 是在基类使用关键字 virtual 声明函数。...您可能想要在基类中定义虚函数,以便在派生类中重新定义该函数更好地适用于对象,但是您在基类中又不能对虚函数给出有意义实现,这个时候就会
  • 为了实现运行时多态,其底层一般采用虚函数表来实现对虚函数的动态绑定,进而在基类对象的引用或指针在调用同名虚函数时可以根据引用或指针指向对象的实际类型调用相应函数。当类继承关系中没有使用多继承时...
  • 虚函数与动态绑定那点事

    千次阅读 2014-02-27 14:10:44
    面向对象编程的概念 ...2)动态绑定:使程序使用继承层次中任意类型的对象,无需关心具体的类型。 在C++,通过引用或者指针调用虚函数,发生动态绑定,引用或指针既可以指向基类对象也可以指向派生类
  • 所谓隐藏是指使用常规的调用方法,派生类对象访问这个函数时,会优先访问派生类中这个函数基类这个函数对派生类对象来说是隐藏起来。 但是隐藏并不意味这不存在或完全不可访问。通过 b->Base::func()访问...
  • 关于虚函数(二)

    2013-09-21 19:49:00
    基类类型的引用或指针绑定到派生类对象对基类对象没有影响,对象本身不会改变,仍为派生类对象对象的实际类型可能不同于该对象引用或指针的静态类型,这是 C++ 中动态绑定的关键。  在编译时确定非 virtual ...
  • 虚函数是在类中被声明为virtual成员函数,当编译器看到通过指针或引用调用此类函数时,其执行晚绑定,也就是运行时多态,即通过指针(或引用)指向的类型信息来决定该函数是哪个类。通常此类指针或引用都...
  • C++虚函数多态

    2015-12-12 09:27:19
    虚函数实现的动态多态性就是: 同一类族中不同类的对象同一函数调用作出不同的响应。虚函数使用方法是: (1)在基类用virtual声明成员函数为虚函数。这样就可以在派生类中重新定义此函数,为它赋予新的功能,...
  • 对虚函数的调用可能在运行时才被解析 面向对象编程核心思想是多态性(polymorphism)。多态性这个词源于希腊语,其含义是“多种形态”,引用或指针静态类型与动态类型不同这一事实是C++语言支持多态性根本...
  • 虚函数和动多态

    2018-11-13 12:00:37
    函数的选择不是基于指针(引用),而是基于对象类型,不同的对象类型将做出不同的编译结果。C++中一般情况下联编也是静态联编,但是一旦涉及到多态和虚函数就必须要使用动态联编了。 假设我们什么都不知道,基类...
  • 如果对象变量指针或引用类型基类。 name调用同一个函数时,默认调用的基类的函数。如果在函数前加上virtual表示虚函数时 ...如果积累已经将成员函数设置为虚函数了 那派生类这个函数声明时候可加可不加v...
  • 派生类可以继承基类的成员,然而遇到与类型相关操作时,派生类必须其重新定义,换句话说,派生类...根据引用或指针绑定对象的类型不同,该调用可能执行基类的版本,也可能执行某个派生类版本。 简略说明 clas
  • (4)学习如何使用虚函数和异类数组实现多态调用。 2 实验内容 2.1 程序模拟银行帐户管理 (1)问题描述创建一个银行账户继承层次,表示银行所有客户账户。所有客户都能在他们银行账户存钱,取钱,并且账户...
  • 概述继承动态绑定定义基类和派生类定义基类成员函数与继承访问控制与继承定义派生类派生类中的虚函数派生类向基类的类型转换派生类构造函数派生类使用基类的成员继承与静态成员派生类声明被用作基类类防止继承...
  • 概述继承动态绑定定义基类和派生类定义基类成员函数与继承访问控制与继承定义派生类派生类中的虚函数派生类对象及派生类向基类的类型转换派生类构造函数派生类使用基类的成员继承与静态成员派生类声明被用作基类...
  • 当我们使用基类的引用或者指针调用基类中定义的一个函数时,我们并不知道该函数真正作用的对象是什么类型,它可能是一个基类的对象也可能是一个派生类的对象。如果该函数是虚函数,则直到运行时才会决定到底执行哪个...
  • 第十五章 面向对象程序设计 15.1 OOP概述 继承 动态绑定 15.2 定义基类和派生类 15.2.1 定义基类 ...派生类中虚函数 派生类对象及派生类对象向基类的类型转换 ...派生类使用基类的成员 ...对虚函数的调用可能在运.
  • 使用动态绑定,可以在一定程度上忽略相似类型的区别,而以统一的方式使用它们的对象,动态绑定也叫作运行时绑定,当用基类的引用或者指针调用一个虚函数时,将发生动态绑定。 2、重要概念:基类/派生类、虚函数、...
  • 一、概述 1、面向对象程序设计核心思想...2、当使用基类的引用(或指针)调用一个虚函数时将发生动态绑定 二、虚函数 1、基类希望它派生类各自定义适合自己版本,基类函数进行覆盖,此时基类应该将这些函数...
  • 当且仅当通过指针或引用调用虚函数时,才会在运行时解析该调用,也只有在这种情况下对象的动态类型才有可能与静态类型不同 上述事实是C++支持多态性的的根本,因为我们能使用这些具有继承关系多种形式而无需...
  • 一、与虚函数不同,“非虚函数总是在编译时根据调用该函数的对象、引用或指针的类型而确定。” 例如pBase为基类指针,指向某继承类。 当利用pBase调用某非虚函数func()时,一定是调用基类的实现,即使在继承类中已经...
  • 重要知识点 面向对象程序设计(object-oriented programming)核心思想是数据抽象、继承和动态绑定。...如果我们通过基类引用或指针调用函数,则使用基类中定义默认实参,即使实际运行是派生类中的函数...
  • C++ virtual的使用

    2021-04-26 10:22:20
    1、对象指针是什么类型的,就调用对应的函数,即使该指针指向了子类等,因为是在编译器编译阶段确定的,此时只能根据对象类型,链接指定的函数指针。 2、如果同一个函数,在不同的子类有不同的重载(开发中一般定义...

空空如也

空空如也

1 2 3 4 5 ... 9
收藏数 176
精华内容 70
关键字:

对虚函数使用基类类型的对象调用