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

当基类指针指向基类中声明的派生类虚函数时,为什么会出现编译时错误?

当基类指针指向基类中声明的派生类虚函数时,会出现编译时错误的原因是因为基类指针只能访问基类中定义的成员函数,而无法直接访问派生类中新增加的成员函数。

虚函数是通过虚函数表来实现的,每个对象都有一个虚函数表指针,指向该对象所属类的虚函数表。虚函数表中存储了虚函数的地址,使得在运行时能够动态地调用派生类中的虚函数。

当基类指针指向基类对象时,编译器可以根据基类指针的静态类型来确定调用的函数地址,因为基类中已经声明了这个虚函数。但是当基类指针指向派生类对象时,编译器只能根据基类指针的静态类型来确定调用的函数地址,而无法确定派生类中新增加的虚函数的地址。

因此,当基类指针指向基类中声明的派生类虚函数时,编译器无法确定调用的函数地址,从而导致编译时错误。

解决这个问题的方法是将基类中的虚函数声明为纯虚函数,即在基类中不给出函数的具体实现,而是要求派生类必须实现该虚函数。这样,基类指针指向派生类对象时,编译器就可以通过虚函数表来确定调用的函数地址,从而避免编译时错误。

腾讯云相关产品和产品介绍链接地址:

  • 腾讯云云服务器(CVM):提供弹性计算能力,满足各种业务需求。产品介绍链接
  • 腾讯云云数据库 MySQL 版:高性能、可扩展的关系型数据库服务。产品介绍链接
  • 腾讯云对象存储(COS):安全、稳定、低成本的云端存储服务。产品介绍链接
  • 腾讯云人工智能:提供丰富的人工智能服务和解决方案,如图像识别、语音识别等。产品介绍链接
  • 腾讯云物联网通信(IoT):为物联网设备提供连接、通信和管理能力。产品介绍链接
  • 腾讯云移动开发:提供移动应用开发和运营的一站式解决方案。产品介绍链接
  • 腾讯云区块链服务(BCS):提供安全、高效的区块链解决方案。产品介绍链接
  • 腾讯云元宇宙:提供虚拟现实(VR)和增强现实(AR)技术,创造沉浸式体验。产品介绍链接
页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

Cpp函数相关知识点

子类child继承base时候,创建一个base指针,让它 指向子类对象,这时候用指针调用print(),此时会自动判断,然后调用子类函数, 如果不加virtual,指针就直接调用...子类继承时候,也连这个函数表一块继承过来,然后把里面的函数指针改成子类函数地址。 由于使用函数导致建立函数表,所以会使程序内存消耗变大,效率降低。...指针指向子类对象时候,在对象使用完毕需要释放,肯定需要调用子类对象析构函数呀,所以这种情况下析构函数也得是函数。...也可以看这段话: 指针可以指向派生类对象(多态性),如果删除该指针delete []p; 就会调用该指针指向派生类析构函数,而派生类析构函数又自动调用 析构函数,这样整个派生类对象完全被释放...如果析构函数不被声明函数,则编译器实施静态绑定, 在删除指针,只会调用析构函数而不调用派生类析构函数, 这样就会造成派生类对象析构不完全。所以,将析构函数 声明函数是十分必要

37020

再探函数

Q1:C++多态如何实现 静态多态: 也称为编译期间多态,编译器在编译期间完成编译器根据函数实参类型(可能进行隐式类型转换),可推断出要调用那个函数,如果有对应函数就调用该函数,否则出现编译错误...2、纯函数是在声明函数,它在没有定义,但要求任何派生类都要定义自己实现方法。在实现纯函数方法是在函数原型后加"=0" 3、声明了纯函数是一个抽象。...只有在析构函数定义为函数,调用操作符delete销毁指向对象指针,才能准确调用派生类析构函数(从该级向上按序调用函数),才能准确销毁数据。...3、函数表存储函数地址,即函数元素是指向成员函数指针,而函数个数在编译时期可以确定,即函数大小可以确定,即大小是在编译时期确定,不必动态分配内存空间存储函数表。...多态函数调用语句被编译成根据指针指向(或引用所引用)对象存放函数地址,在函数查找函数地址,并调用函数一系列指令。

86220

第 15 章 面向对象程序设计

而对于非虚函数调用是在编译进行绑定。类似的,通过对象进行函数函数或非虚函数)调用也在编译绑定。 一旦某个函数声明函数,则在所有派生类它都是函数。...而对于派生类覆盖函数,其形参必须相同,返回类型也要与匹配。而函数返回类型是本身指针或引用且可进行类型转换,也是允许。 ?...---- 15.7 构造函数与拷贝控制 需要 delete一个指针,该指既可以指向对象,也可以指向派生类对象,此时编译器必须明确执行派生类指针。...如前所述,一个存在拷贝控制成员编译器不会为这个合成移动操作。对于需要定义析构函数,也是如此。...构造函数具有默认实参,实参不会被继承,而是派生类获得多个继承构造函数,每个构造函数分别省略掉一个含有默认实参形参。

1K30

继承

派生类之间关系: 派生类对象可以使用(公有的)方法。 指针可以在不进行显示类型转换情况下指向派生类对象,但只能调用方法。...动态联编主要包含一下方面: 成员函数必须声明函数,即前面加virtual。 如果对某个成员函数声明函数,则其派生类该成员函数不需要再声明。...函数表存储了为对象进行声明函数地址。通常情况下,对象包含一个指向该类函数指针。...,则该函数地址也添加到函数。...抽象 函数声明结尾处为=0,该函数称为纯函数声明包含纯函数,则不能创建该类对象。 在函数原型中使用=0指出是一个抽象,在可以不定义该函数

69420

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

{}; virtual B& func() {}; //重写了函数 }; 二、为什么要设计函数 我们知道派生类拥有定义函数,但是对于某些函数,我们希望派生类各自定义适合于自己版本函数...(不困省不省略,该函数在子类也是函数类型) virtual只能出现内部声明语句之前而不能用于外部函数定义 override: 父函数不可使用 放在子类函数参数列表后(如果函数有尾指返回类型...,但是子类没有覆盖(重写)这个函数,而子类出现了一个与函数名相同、但是参数不同函数,这仍是合法。...必须传入a和b }; 七、动态绑定 概念:某个函数通过指针或引用调用时,编译器产生代码直到运行时才能确定到该调用哪个版本函数(根据该指针所绑定对象) 必须清楚动态绑定只有当我们通过指针或引用调用...“函数才会发生,如果通过对象进行函数调用,那么在编译阶段就确定该调用哪个版本函数了(见下面的演示案例) 当然,如果派生类没有重写函数,那么通过指针指向派生类,调用函数还是调用函数

3.9K31

c++和继承面试点25连问

运行时多态简单来讲就是:使用指针或者引用指向一个派生类对象,在非虚继承情况下,派生类直接继承指针,然后使用派生类函数去覆盖函数,这样派生类对象通过指针访问到函数就是派生类函数了...,此时我们把A析构函数修改为virtual,看看结果: A() B() ~B() ~A() 一般情况下,只有当一个被用作才需要使用析构函数,这样做作用是一个指针删除派生类对象...基于多态作用,这个指向派生类指针先调用派生类析构函数,然后再调用析构函数。...所以派生类,析构函数一定要是函数。 8....,结合我们知道,如果使用了空指针,就会发生段错误,那这里肯定也会发生段错误,但实际上编译执行后并没有产生错误,print函数被正确执行了,这就很尴尬了,这是为什么呢?

93210

轻松搞定面试

函数作用是允许在派生类重新定义与类同名函数,并且可以通过指针或引用来访问派生类同名函数,达到多态目的。 2.什么是纯函数,什么是纯,有什么作用?...纯函数只有函数名字而不具备函数功能,不能被调用。它只是通知编译系统:“在这里声明一个函数,留待派生类定义”。在派生类对此函数提供定义后,它才能具备函数功能,可被调用。...当然,并不是要把所有析构函数都写成函数。因为里面有函数时候,编译器会给添加一个函数表,里面来存放函数指针,这样就会增加存储空间。...虚拟继承与普通继承不同是,虚拟继承可以防止出现diamond继承,一个派生类同时出现了两个子对象。也就是说,为了保证这一点,在虚拟继承情况下,子对象布局是不同于普通继承。...为实现动态联编,编译器为每个包含函数创建一个表,称为vtable,在vtable编译器放置了特定函数地址,在每个带有函数编译秘密地设置一个函数指针,称为vptr,指向对象

66220

C++:28 --- C++内存布局(上)

声明了一个对象实例,用点“.”操作符访问成员c1,由于编译就完全知道对象布局情况,所以可以直接计算偏移量。 访问继承层次,多层成员变量,情况又如何呢?...当然,这个检查只有当指针被显示或者隐式转化为相关类型指针才进行;当在派生类对象调用方法,从而派生类指针在后台被转化为一个Const “this” 指针,这个检查就不需要进行了,因为在此时...正如你猜想继承关系存在,强制转化开销会比较大。具体说来,和访问成员变量开销相当。...一般说来,派生类访问成员,应该先强制转化派生类指针指针,然后一直使用指针来访问成员变量。这样做,可以避免每次都要计算地址开销。 见下例。...不管“->”操作符左边指针表达式类型如何,调用函数都是由指针实际指向实例类型所决定 。比如,尽管ppq类型是P*,ppq指向Q实例,调用仍然是Q::pvf()。

1K20

C++多态特性

它可以通过两种方式实现: (1)函数(virtual function) 函数是在声明函数,它可以被派生类重写,实现多态效果。...在派生类实现函数可以覆盖同名函数,而且会在运行时对象类型上调用合适函数。通过将指针或引用指向派生类对象,可以实现动态多态性。 (2)模板(template)。...在父通过关键字virtual声明函数函数,子类可以覆盖并重新实现(重写)该函数通过父指针或引用调用函数,实际调用是子类实现,而不是父实现。这样就实现了多态....函数特殊情况: 斜变 派生类重写函数,与函数返回值类型不同。 函数返回对象指针或者引用. 派生类函数返回派生类对象指针或者引用时....delete p1; delete p2; //arr2未释放 return 0; } 运行结果: 显然,在未实现多态情况下,指针指向派生类,调用析构函数都只能调用析构函数

12970

硬核 | C++ 基础大全

实际上,一个包含函数编译器会为该类生成一个函数表,保存该类函数地址,同样,派生类继承派生类自然一定有函数,所以编译器也会为派生类生成自己函数表。...当我们定义一个派生类对象编译器检测该类型有函数,所以为这个派生类对象生成一个函数指针指向该类型函数表,这个函数指针初始化是在构造函数完成。...后续如果有一个类型指针指向派生类,那么调用函数,就会根据所指真正对象函数指针去寻找函数地址,也就可以调用派生类函数函数以此实现多态。...因为一个指针指向一个派生类对象,在派生类对象针对函数参数缺省值进行了重定义, 但是缺省参数值是静态绑定,静态绑定绑定是静态类型相关内容,所以会出现一种派生类函数实现方式结合了缺省参数值调用效果...哪些函数不能是函数 构造函数,构造函数初始化对象,派生类必须知道函数干了什么,才能进行构造;函数,每一个有一个表,每一个对象有一个指针指针在构造函数初始化; 内联函数,内联函数表示在编译阶段进行函数替换操作

1.2K10

【笔记】《C++Primer》—— 第15章:面向对象程序设计

任何构造函数以外非静态函数都可以是函数,如果声明函数,那么派生类对应函数都隐式函数 通过抽象,我们使用动态绑定可以实现接口与实现分离,函数声明出接口,然后指针指向不同派生类实现来动态调用...这里有一个特别的,即便处理指针,此指针指向派生类,我们也不能隐式转换到这个派生类,如果中含有函数,我们可用用dynamic_cast强制转换 15.3 函数 通过对指针或引用来调用函数时会出现动态绑定...,那必须名称和形参都一致,否则编译认为这两个函数是独立,而不会产生覆盖 派生类函数返回类型也需要与一致,除非虚函数返回类型是本身引用或指针为了多态性会有特例 如果想要保证某个函数一定会被覆盖...,目标的静态类型决定了其是否可见 和其他作用域一样,派生类可以重用名字,因此名字重叠派生类名字隐藏名字,类似函数情形。...或constexpr,而是这个构造函数继承声明属性 构造函数中有默认实参,这些实参不会被继承,而是派生类会得到多个继承构造函数,每个构造函数省略一个有默认实参形参 大多数时候派生类继承所有构造函数

51320

【C++进阶学习】第四弹——多态——迈向C++更深处关键一步

函数是在声明,并在派生类重写函数。...2、通过指针或引用调用函数: 多态通常通过指针或引用来实现。使用指针或引用指向派生类对象,调用函数将根据对象实际类型(而不是指针或引用类型)来决定调用哪个函数。...在C++11及以后版本,可以使用override关键字显式声明派生类函数是重写函数,这有助于编译器检查是否正确重写了函数。...这是因为通过指针删除派生类对象,如果析构函数不是函数,将只会调用析构函数,而不会调用派生类析构函数,这可能导致资源泄漏。...这样做可以增加代码可读性,并且能够帮助编译器检测错误,比如试图重写一个并不存在函数

10710

C++系列笔记(五)

使用函数实现多态行为 可通过Fish指针或Fish引用访问Fish对象,这种指针或引用可指向Fish、Carp等对象。但你不需要知道也不关心它们指向是哪种对象。...为什么需要虚构函数 上面的代码如果加入析构函数释放内存,对于使用new在自由储存区实例化派生类对象,如果将其赋值给指针,并通过该指针调用delete,将不会调用派生类析构函数,这可能导致资源未释放...抽象和纯函数 不能实例化被称为抽象,这样只有一个用途,那就是从它派生出其他。在 C++,要创建抽象,可声明函数。...注意:C++关键字virtual含义随上下文而异(我想这样做目的很可能是为了省事),对其含义总结如下: 在函数声明,virtual意味着指针指向派生对象,通过它可调用派生类相应函数。...可将复制构造函数声明函数吗 根本不可能实现复制构造函数,因为在方法声明中使用关键字virtual,表示它将被派生类实现覆盖,这种多态行为是在运行阶段实现

66530

C++关键知识点梳理

:借助函数可实现对象指针调用派生类对象对应函数。...每个继承子类都有一个指针(占用一个指针存储空间,4字节)和表(不占用对象存储空间)派生类重新定义函数,则将派生类函数地址添加到函数。...一个指针指向一个派生类对象函数指针指向派生类对象函数表。调用函数,由于派生类对象重写了派生类对应函数表项,在调用时会调用派生类函数,从而产生多态。...析构函数:为了防止delete指向派生类对象指针只调用析构函数引起内存泄漏using namespace std;class Base {public: virtual ~ Base...,则delete pb只会调用Base析构函数函数函数声明时候加上=0,包含纯函数是抽象,不可实例化,纯函数必须被派生类实现。

94930

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

运行时多态允许通过指针或引用来调用派生类函数,实现了动态绑定。 2.多态定义和实现 2.1多态构成条件 多态实现通常依赖于函数。在声明函数,然后在派生类中进行重写(覆盖)。...nullptr(这个也是看平台) 总结一下派生类表生成: 先将表内容拷贝一份到派生类 如果派生类重写了某个函数,用派生类自己函数覆盖函数 派生类自己新增加函数按其在派生类声明次序增加到派生类最后...指针或引用调用函数编译器生成机器代码确实先访问对象函数指针(vptr),再通过函数表(vtable)找到实际要调用函数地址,最终进行调用。...这种动态绑定过程使得程序在运行时能够根据对象实际类型来调用正确函数,实现了多态性 为什么多态必须要用指针 / 引用来调用函数,而用对象调用却不行 派生类对象赋值给对象...因此,对象函数调用绑定到函数表上,而无法访问派生类函数

51410

QT(C++)面试总结

单继承和多继承 单继承(派生类只从一个直接继承)派生类定义: class 派生类名:继承方式 名 { 新增成员声明; } 多继承派生类定义: class 派生类名:继承方式1...多态:同一操作作用于不同对象,可以有不同解释,产生不同执行结果。在运行时,可以通过指向指针,来调用实现派生类方法。...C++,实现多态有以下方法:函数,抽象,覆盖,模板(重载和多态无关)。 C++ (纯函数和抽象) a. 纯函数是一个在只有声明函数,在无定义。...如果是class是struct关键字描述,那么默认访问属性是什么? 出现这种情况,到底默认是public继承还是private继承,取决于子类而不是。...…… #endif 注意事项: #ifndef AAA #define AAA … int i; … #endif 里面有一个变量定义 在vc链接出现了i重复定义错误,而在c成功编译

1.9K10

《逆袭进大厂》第三弹之C++提高篇79问79答

(3)使用抽象注意: 抽象只能作为来使用,其纯函数实现由派生类给出。如果派生类没有重新定义纯函数,而只是继承函数,则这个派生类仍然还是一个抽象。...a.编译多态性:通过重载函数实现  b.运行时多态性:通过函数实现。 2、函数  函数是在中被声明为virtual,并在派生类重新定义成员函数,可实现成员函数动态重载。...把你知道都说一说 1) 构造函数,构造函数初始化对象,派生类必须知道函数干了什么,才能进行构造;函数,每一个有一个表,每一个对象有一个指针指针在构造函数初始化; 2)...函数是为了实现动态编联产生,目的是通过类型指针指向不同对象,自动调用相应、和类同名函数(使用同一种调用形式,既能调用派生类又能调用同名函数)。...一个成员函数声明函数之后,其派生类同名函数自动成为函数,在派生类重新定义此函数要求函数名、返回值类型、参数个数和类型全部与函数相同。

2.2K30

C++纯函数与抽象

如果不定义析构函数删除一个指向派生类对象指针,会调用析构函数派生类析构函数未被调用,造成内存泄露。...析构函数工作方式是:最底层派生类析构函数最先被调用,然后各个析构函数被调用。这样,删除指向派生类指针,就会首先调用派生类析构函数,不会有内存泄露问题了。...一般情况下,如果类没有函数,就不用去声明析构函数且仅里包含至少一个函数时候才去声明析构函数。只有当一个被用来作为时候,才有必要将析构函数写成函数。...在有函数实例,分配了指向这个表指针内存,所以,当用父指针来操作一个子类对象实体时候,这张函数表就指明了实际所应该被调用函数。...所以纯函数声明就是在告诉子类设计者,“你必须实现这个函数,但我不知道你怎样实现它”。 值得特别注意是,由于抽象至少有一个函数没有实现,所以抽象无法被实例化,否则编译器会报错。

1.5K20

C++基础-多态

如果不将析构函数声明函数,那么如果一个函数形参是指针,实参是指向堆内存派生类指针函数返回作为实参派生类指针将被当作指针进行析构,这会导致资源释放不完全和内存泄漏;要避免这一问题,...可将析构函数声明函数,那么函数返回,作为实参派生类指针就会被当作派生类指针进行析构。...如果派生类没有函数,那么派生类函数每个元素都指向函数派生类对象只含一份 VFT 指针私有成员都会在派生类对象占用内存,但 VFT 指针不会在派生类占用内存。...C++关键字 virtual 被用于实现两个不同概念,其含义随上下文而异,如下: 在函数声明, virtual 意味着指针指向派生对象,通过它可调用派生类相应函数。...• 派生类中被声明为 override 函数是否是对应函数覆盖?确保没有有手误写错。 编程实践:在派生类声明要覆盖函数函数,务必使用关键字 override 7.

84820

《逆袭进大厂》之C++篇49问49答

33、为什么析构函数一般写成函数 由于多态性,指针可以指向派生类对象,如果删除该指针,就会调用该指针指向派生类析构函数,而派生类析构函数又自动调用析构函数,这样整个派生类对象完全被释放...如果析构函数不被声明函数,则编译器实施静态绑定,在删除指针,只会调用析构函数而不调用派生类析构函数,这样就会造成派生类对象析构不完全,造成内存泄漏。...上图中展示了表和指针对象和派生类对象模型,下面阐述实现多态过程: (1)编译器在发现中有函数自动为每个含有函数生成一份表,该表是一个一维数组,表里保存了函数入口地址...在构造子类对象先调用父构造函数,此时,编译器只“看到了”父,并为父对象初始化指针,令它指向表;调用子类构造函数,为子类对象初始化指针,令它指向子类表 (4)派生类函数没有重写...,派生类指针指向表;派生类函数重写派生类指针指向是自身表;派生类中有自己函数,在自己表中将此函数地址添加在后面 这样指向派生类指针在运行时

2K10
领券