首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

为什么基类对象必须是调用派生虚函数的引用?

基类对象必须是调用派生虚函数的引用,是因为在C++中,虚函数的调用是通过指向基类对象的指针或引用来实现的。当一个派生类对象被基类指针或引用指向时,调用虚函数会根据对象的实际类型来决定调用哪个函数。

如果基类对象不是引用,那么编译器将无法确定对象的实际类型,从而无法正确地调用虚函数。因此,为了确保虚函数的正确调用,必须使用指向基类对象的引用来调用虚函数。

例如,以下代码将无法正确调用派生类的虚函数:

代码语言:txt
复制
class Base {
public:
    virtual void func() {
        cout << "Base::func()"<< endl;
    }
};

class Derived : public Base {
public:
    virtual void func() {
        cout << "Derived::func()"<< endl;
    }
};

int main() {
    Base obj;
    obj.func(); // 调用基类的虚函数
    return 0;
}

在上面的代码中,虚函数func()被声明为基类Base的成员函数,并被派生类Derived重写。但是,当我们创建一个基类对象obj并调用其虚函数时,编译器无法确定对象的实际类型,因此无法正确调用派生类的虚函数。

为了解决这个问题,我们可以使用指向基类对象的引用来调用虚函数:

代码语言:txt
复制
int main() {
    Base obj;
    Base& ref = obj;
    ref.func(); // 调用派生类的虚函数
    return 0;
}

在上面的代码中,我们创建了一个指向基类对象obj的引用ref,并通过引用调用虚函数func()。由于引用指向的是一个派生类对象,因此编译器可以正确地调用派生类的虚函数。

总之,基类对象必须是调用派生虚函数的引用,是因为虚函数的调用需要通过指向基类对象的指针或引用来实现,而指针或引用必须指向一个派生类对象,以便正确调用派生类的虚函数。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

派生函数和非虚函数继承效果

base3,因为eye个普通函数,在编译阶段就确定好被谁调用,所以他只认哪个指针指向自己,这里Animal指针指向,所以他就调用Animal里面的,普通函数为子类提供“强制实现”,也就是只要是父指针调用普通函数...,那就是父普通函数函数作用,主要是为了让父指针可以调用子类函数,这种在运行时才决定调用哪个函数 1、函数:   C++函数主要作用是“运行时多态”,父中提供函数实现,为子类提供默认函数实现...子类可以重写父函数实现子类特殊化。 2、纯函数:   C++中包含纯函数,被称为“抽象”。抽象不能使用new出对象,只有实现了这个纯函数子类才能new出对象。   ...3、普通函数:   普通函数静态编译,没有运行时多态,只会根据指针或引用“字面值”对象调用自己普通函数。   普通函数为子类提供“强制实现”。   ...因此,在继承关系中,子类不应该重写父普通函数,因为函数调用至于对象字面值有关。 参考链接

7910

C++中多态

Person对象买票全价,Student对象买票半价。 那么在继承中,需要以下条件才能构成多态: ①被调用函数必须函数,且派生必须函数进行重写/覆盖。...②必须通过指针或引用调用函数。...反思构成多态条件 通过分析,我们可以好好反思一下构成多态条件,为什么函数重写,为什么对象指针或引用调用函数。 ①为什么函数覆盖/重写: 因为要对派生表进行覆盖。...在调用重写函数时候,如果指向派生对象,那么就必须从这个派生表中拿到这个函数地址。 ②为什么对象指针或引用调用函数: 首先,函数必须写在中。...其次,指针或引用派生对象时候,在切片后,指向派生对象中属于成员那一部分,但总体来说依然指向派生,当需要调用重写函数时候,就会去成员那一部分中找接口,再去派生中找定义

83320
  • 总结继承和多态一些问题

    切片: 我们都知道,多态条件函数重写和必须通过指针或者引用调用函数。。那么为什么一定是需要指针或引用呢? 先来看看不用指针或引用,也就是使用对象调用函数。...因此,简单总结就是:派生对象赋值给对象,切片会把派生中包含成员变量值拷贝过去,但是派生表不会给拷贝过去,则函数中这个对象,所以无法实现多态。...而指针或者引用是直接指向派生对象,不会进行拷贝赋值,这样函数派生函数表,故能实现多态。 5.inline函数可以是函数吗?...因为有时候我们难免会用指针或引用指向派生对象析构函数函数的话,可以准确地调用派生析构函数。 8.对象访问普通函数快还是函数更快? 首先如果普通对象一样快。...如果指针对象或者引用对象,则调用普通函数快,因为构成多态,运行时调用函数需要到函数表中去查找。 9.什么抽象?抽象作用? 一个函数如果函数的话,那么这个便是抽象

    45020

    C++进阶:详解多态(多态、函数、抽象以及函数原理详解)

    运行时多态: 通过函数和继承实现,在运行阶段确定函数调用。运行时多态允许通过指针或引用调用派生函数,实现了动态绑定。...通过指针或引用调用函数时,将根据对象实际类型调用相应派生函数 从上面这段话我们知道在继承中要构成多态还有两个条件: 必须通过指针或者引用调用函数调用函数必须函数...对象指针 / 引用调用函数原理是什么?...这种动态绑定过程使得程序在运行时能够根据对象实际类型来调用正确函数,实现了多态性 为什么多态必须要用指针 / 引用调用函数,而用对象调用却不行 当派生对象赋值给对象时...多态必须使用指针/引用调用函数原因主要是因为指针/引用可以在运行时指向派生对象,而且能正确地调用派生函数

    53810

    【C++】———— 多态

    二、多态定义和实现 1.多态构成条件 在继承中要形成多态还有两个条件: 调用必须要通过指针或者引用调用函数调用函数必须函数,且派生必须含有对函数重写 这里我们插入一个概念...,你传递调用函数,传递子类就调用子类函数, 在重写函数时,派生函数在不加virtual关键字时,虽然也可以构成重写(因为继承后函数被继承下来了在派生依旧保持函数属性...函数重写两个例外: 2.1协变 派生重写函数时,与函数返回值类型不同。即函数返回对象指 针或者引用派生函数返回派生对象指针或者引用时,称为协变。...纯函数规范了派生必须重写,另外纯函数更体现出了接口继承。 注意这里包含,只要里面有一个有纯函数,就是抽象,就无法实例化对象,间接强制派生重写。...普通函数继承一种实现继承,派生继承了函数,可以使用函数,继承函数实现。函数继承一种接口继承,派生继承函数接口,目的是为了重写,达成多态,继承接口。

    10510

    C++多态特性

    派生中实现函数可以覆盖同名函数,而且会在运行时对象类型上调用合适函数。通过将指针或引用指向派生对象,可以实现动态多态性。 (2)模板(template)。...父指针/引用指向子类对象必须指针或者引用调用函数,才能进行多态操作。 二、何为函数? C++中函数一种特殊成员函数,用于在继承关系中实现多态性。...在父中通过关键字virtual声明函数函数,子类可以覆盖并重新实现(重写)该函数。当通过父指针或引用调用函数时,实际调用子类中实现,而不是父实现。这样就实现了多态....函数特殊情况: 斜变 派生重写函数时,与函数返回值类型不同。 函数返回对象指针或者引用. 派生函数返回派生对象指针或者引用时....为什么析构函数要实现多态? 因为析构函数实现多态了以后,才能实现在析构派生时,各自调用自己析构函数,防止内存泄漏!

    13470

    再探函数

    函数模板使用 动态多态 在函数前加上virtual关键字,在派生中重写该函数,运行时将会根据所指对象实际类型来调用相应函数,如果对象类型派生,就调用派生函数,如果对象类型,...必须函数派生一定要重写函数) ---- Q2:什么函数,与函数区别 1、定义一个函数函数,不代表函数为不被实现函数。...那我现在有一个抽象对象,我要调用接口,调用哪个? ---- Q5:析构函数为什么要定义成函数?...只有在析构函数定义为函数时,调用操作符delete销毁指向对象指针时,才能准确调用派生析构函数(从该级向上按序调用函数),才能准确销毁数据。...多态函数调用语句被编译成根据指针所指向(或引用引用对象中存放函数地址,在函数表中查找函数地址,并调用函数一系列指令。

    86720

    《C++Primer》第十五章 面向对象程序设计

    函数 当我们使用引用或者指针调用一个成员函数时候会发生动态绑定,直到运行时我们才能知道到底调用了哪个版本,所以所有的函数必须有定义。...即如果我们通过引用或者指针调用函数,则使用中定义默认残,即使实际运行派生函数版本也是如此。 如果函数使用哪个默认实参,那么派生中定义默认实参最好一致。 5....,则编译器产生代码将在运行时确定到底运行函数哪个版本,依据对象动态类型 如果mem不是函数或者我们通过对象(非引用或者指针)进行调用,则编译器将产生一个常规函数调用 5....函数与作用域 从名字查找先于类型检查我们可以得知为什么派生函数为什么必须有相同形参列表了。...假如派生函数接收实参不同,那么我们就无法通过引用或者指针调用派生函数了。

    1.2K20

    【C++】多态

    那要想实现多态,必须满足两个条件 2.2.1 条件1:函数重写 第一个条件: 被调用函数必须函数,且派生必须函数进行重写 那什么函数重写呢?...2.2.2 条件2:指针或者引用调用函数 第二个条件: 必须通过指针或者引用调用函数 我们先学语法,后面会给大家讲原理。...另外还可以是指针去调用: 我们说必须指针或者引用调用函数,那就意味着用对象是不行: 虽然没有报错,但是并没有实现多态。...但是有要求函数必须返回对象指针或引用派生函数必须返回派生对象指针或引用,我们把这种情况称为协变。...那第二个条件:必须指针或引用调用,满足吗? ,其实也是满足

    11010

    C++:44---关键字virtual、override、final

    ,其解析过程发生在编译时而非运行时 派生可以不覆盖(重写)它继承函数 重写(覆盖)概念与规则 派生重写(覆盖)函数,其中函数名,参数列表,返回值类型都必须一致,并且重写(覆盖)函数...virtual函数 函数在子类和父访问权限可以不同 相关规则: ①如果函数返回值类型基本数据类型:返回值类型必须相同 ②如果函数返回值类型本身指针或引用:返回值类型可以不同,但派生返回值类型小于返回值类型...{}; virtual B& func() {}; //重写了函数 }; 二、为什么要设计函数 我们知道派生会拥有定义函数,但是对于某些函数,我们希望派生各自定义适合于自己版本函数...fun1时,必须传入a和b }; 七、动态绑定 概念:当某个函数通过指针或引用调用时,编译器产生代码直到运行时才能确定到该调用哪个版本函数(根据该指针所绑定对象必须清楚动态绑定只有当我们通过指针或引用调用...“函数”时才会发生,如果通过对象进行函数调用,那么在编译阶段就确定该调用哪个版本函数了(见下面的演示案例) 当然,如果派生没有重写函数,那么通过指针指向于派生时,调用函数还是调用函数

    4K31

    【多态】【表指针与表】【多继承中多态】

    多态定义和实现 1.多态构成条件 必须通过 指针或者引用 调用函数调用函数 必须函数,且派生必须函数进行重写 那么问题来啦,什么函数?重写又是什么?请看下面!...即函数返回对象指针或引用派生函数返回派生对象指针或引用时,称为协变。...函数名、返回值类型、参数都必须相同(协变除外) 两个函数必须函数 对于 隐藏(重定义) 条件: 两个函数分别在派生作用域 函数名相同即可 两个派生同名函数不构成重写的话则构成隐藏...派生继承后也不能实例化出对象,只有派生重写纯函数派生才能实例化出对象。纯函数规范了派生必须重写,另外纯函数更体现出了接口继承。...void Func(A& a) //为什么这里不能对象?而一定要是父引用或指针呢?

    1.2K30

    C++纯函数与抽象

    函数必须非静态成员函数(且非构造函数),其访问权限public。那么: (1)为什么静态成员函数不能为函数?...如果定义为函数,那么它就是动态绑定,也就是在派生中可以被覆盖,这与静态成员函数定义(在内存中只有一份拷贝,通过名或对象引用访问静态成员)本身就是相矛盾。...如果不定义析构函数,当删除一个指向派生对象指针时,会调用析构函数派生析构函数未被调用,造成内存泄露。...析构函数工作方式:最底层派生析构函数最先被调用,然后各个析构函数调用。这样,当删除指向派生指针时,就会首先调用派生析构函数,不会有内存泄露问题了。...这张表解决了继承、覆盖问题,保证使用指向子类对象实体指针或引用,能够访问到对象实际函数

    1.5K20

    C++系列笔记(五)

    使用函数实现多态行为 可通过Fish指针或Fish引用访问Fish对象,这种指针或引用可指向Fish、Carp等对象。但你不需要知道也不关心它们指向哪种对象。...可以用下面代码所示: pFish->Swim(); myFish.Swim(); 你希望通过这种指针或引用调用Swim()时,如果它们指向Tuna对象,则可像Tuna那样游泳,若指向Carp对象...为什么需要虚构函数 上面的代码如果加入析构函数释放内存,对于使用new在自由储存区中实例化派生对象,如果将其赋值给指针,并通过该指针调用delete,将不会调用派生析构函数,这可能导致资源未释放...抽象提供了一种非常好机制,让您能够声明所有派生必须实现函数。抽象常被简称为ABC。ABC有助于约束程序设计。...可将复制构造函数声明为函数吗 根本不可能实现复制构造函数,因为在方法声明中使用关键字virtual时,表示它将被派生实现覆盖,这种多态行为在运行阶段实现

    67130

    【C++深度探索】全面解析多态性机制(一)

    1.什么多态 在C++中,多态(Polymorphism)指通过指针或引用来访问派生对象一种机制。简单来说,它允许我们在类型指针或引用调用派生对象成员函数。...通过使用指针或引用指向派生对象,并调用函数,实际上在运行时会根据对象实际类型调用合适函数。...在继承中要构成多态有两个条件: 必须通过指针或者引用调用函数调用函数必须函数,且派生必须函数进行重写 例如: class Person { public: virtual...4.函数重写两个例外 协变(派生函数返回值类型不同) 即函数返回对象指针或者引用派生函数返回派生对象指针或者引用时,称为协变。...而我们在编程中要实现多态就必须要满足两个条件:一个指针或引用调用函数,另一个则是中定义函数并且在派生中对该函数进行重写;这两个条件缺一不可,这与多态实现底层原理有关,我们后续再了解

    11310

    多态讲解

    但是要满足多态在继承中就要有以下两个条件: 必须通过指针或者引用调用函数调用函数必须函数,且派生必须函数进行重写 如果对象直接调用的话就不会构成多态,上图中函数覆盖就是我们所说函数重写...,并且重写了函数buyticket,在Func函数中我们就引用person对象,然后调用buyticket函数 然后在main函数中我们person和student各自创建了一个对象,分别调用...即函数返回对象指针或者引用派生函数返回派生对象指针或者引用时,称为协变。...b对象派生d对象不一样,这里我们发现Func1完成了重写,所以d表中存重写Derive::Func1,所以函数重写也叫作覆盖,覆盖就是指表中函数覆盖。...这样就实现出了不同对象去完成同一行为时,展现出不同形态。 反过来思考我们要达到多态,有两个条件,一个函数覆盖,一个对象指针或引用调用函数。反思一下为什么

    6210

    轻松搞定面试中

    包括:函数,纯函数继承... 1.什么函数,有什么作用? 在用virtual声明成员函数函数。这样就可以在派生中重新定义此函数,为它赋予新功能,并能方便地被调用。...函数作用是允许在派生中重新定义与类同名函数,并且可以通过指针或引用来访问派生同名函数,达到多态目的。 2.什么函数,什么,有什么作用?...因为纯函数不能被调用,包含纯函数无法建立对象。 抽象作用是作为一个共同,或者说,为一个族提供一个公共接口。 3.为什么有的析构函数需要设为virtual?...显然:当我们构造一个子类对象时,先调用构造函数,构造子类中部分,子类还没有构造,还没有初始化,如果在构造中调用函数,如果可以的话就是调用一个还没有被初始化对象,那是很危险,所以...c++通过下面两个操作符提供RTTI: (1)typeid:返回指针或引用所指对象实际类型。 (2)dynamic_cast:将类型指针或引用安全转换为派生类型指针或引用

    66520

    CC++面试常问题集(2)

    三,赋值运算符重载函数  赋值运算符重载函数也不会被子类继承,只是在子类赋值运算符重载函数中会调用赋值运算符重载函数。 7、析构函数为什么要用virtual析构函数?...假设中采用是非虚析构函数,当删除指针指向派生对象时就不会触发动态绑定,因而只会调用析构函数,而不会调用派生析构函数。...函数必须根据对象类型才能知道调用哪一个函数,故函数一定要在对象基础上才可以,两者一个与实例相关,一个相关。 4....核心理念就是通过访问派生定义函数。它提供了一种接口界面。允许在派生中对函数重新定义。由多态方式调用时候动态绑定。...就是指针或引用有可能指向不同派生对象,对于非虚函数,执行时实际调用函数对象类型即为该指针或引用静态类型(类型);而对于函数,执行时实际调用函数对象类型为该指针或引用所指对象实际类型

    1.2K10

    【C++】从零开始认识多态

    我们运行看看: 多态调用:运行时,到指定对象表中找函数调用(指向调用函数,指向子类调用子类函数) 普通调用:编译时,调用对象是哪个类型,就调用函数。...多态构成条件: 必须通过指针或者引用调用函数(virtual修饰成员函数) 被调用函数必须函数,且派生必须函数进行重写(父子虚函数要求三同) 函数重写(覆盖):派生中有一个跟完全相同函数...协变:派生重写函数时,与函数返回值类型不同: 函数返回对象指针或者引用 派生函数返回派生对象指针或者引用 这样情况称为协变。...那我们来看看现在满不满足多态条件: 必须通过指针或者引用调用函数(virtual修饰成员函数) 被调用函数必须函数,且派生必须函数进行重写(父子虚函数要求三同) 在编译时候...传派生,因为多态函数指针,那么就会切片出来一个函数派生),那么就会在派生调用对应函数。 这样就实现了执行谁就调用谁!!! 运行过程中去表中找对应函数调用

    8310

    常见c和cpp面试题目汇总(一)

    关键字可有可无 override,派生覆盖函数,实现接口重用;特征:不同范围(派生)、函数名字相同、参数相同、必须有virtual关键字(必须函数) overwrite,派生屏蔽了其同名函数...九、函数怎么实现: 每一个含有函数都至少有有一个与之对应函数表,其中存放着该类所有函数对应函数指针(地址);示例对象不包含函数表,只有指针;派生会生成一个兼容函数表...,还没有内存空间,更没有函数表地址用来调用函数即构造函数了 2、析构函数最好声明为函数 首先析构函数可以为函数,当析构一个指向派生指针时,最好将析构函数声明为函数,否则可以存在内存泄露问题...如果析构函数不被声明成函数,则编译器实施静态绑定,在删除指向派生指针时,只会调用析构函数而不调用派生析构函数,这样就会造成派生对象析构不完全。...因为引用(或指针)既可以指向对象也可以指向派生对象,这一事实是动态绑定关键。用引用(或指针)调用函数在运行时确定,被调用函数引用(或指针)所指对象实际类型所定义

    1.3K31

    C++之多态

    在继承种构成多态要满足两个条件: 必须通过指针或者引用调用函数(该指针或者引用操作派生那一部分内容) 被调用函数必须函数,且派生必须函数进行重写。...即函数返回对象指针或者引用派生函数返回派生对象指针或者引用时(返回值类型为继承关系指针),称为协变。...包含纯函数,称为抽象。 抽象不能实例化处对象,它派生也不能实例化处对象,只有派生重写纯函数之后才能实例化出对象。 纯函数规范了派生必须重写,纯函数体现出接口继承。...Student对象调用同一个函数Func得到不同结果,这是因为调用函数传参对象,而派生对象调用函数传参派生对象那一部分。...导致指针p调用成员函数派生指针p调用派生成员函数。 简单来说: 普通函数调用是传谁调用谁; 符合多态函数调用就是指向谁调用谁。

    34540
    领券