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

轻松搞定面试中的“虚”

因为纯虚函数是不能被调用的,包含纯虚函数的类是无法建立对象的。 抽象类的作用是作为一个类族的共同基类,或者说,为一个类族提供一个公共接口。 3.为什么有的类的析构函数需要设为virtual?...是否每个类的析构函数都要设置成virtual?是否可以将析构函数设置成内联函数。 这样做是为了当用一个基类的指针删除一个派生类的对象时,派生类的析构函数会被调用。...只是你如果这么写的话编译器不会给你调用子类的实现,而是还是调用基类的实现。  在析构函数中也不要调用虚函数。...在析构的时候会首先调用子类的析构函数,析构掉对象中的子类部分,然后在调用基类的析构函数析构基类部分,如果在基类的析构函数里面调用虚函数,会导致其调用已经析构了的子类对象里面的函数,这是非常危险的。...虚拟继承与普通继承不同的是,虚拟继承可以防止出现diamond继承时,一个派生类中同时出现了两个基类的子对象。也就是说,为了保证这一点,在虚拟继承情况下,基类子对象的布局是不同于普通继承的。

68120

每日一问06 构造函数可以是虚函数吗

,为什么 和普通函数对比 首先,C++不支持虚拟构造函数。...关于C++为什么不支持虚拟构造函数,Bjarne很早以前就在C++ Style and Technique FAQ里面做过回答:A virtual call is a mechanism to get...根本说不清楚:必须创建好了,才能用,不懂 抽象和具体关系.接口不属于具体一个类 析构函数可以是虚函数吗,为什么 参考思路: 可以是 析构函数 执行顺序是 派生类 ,基类 如果析构函数不被声明成虚函数,则编译器实施静态绑定...,在删除指向派生类的基类指针时,只会调用基类的析构函数而不调用派生类析构函数,这样就会造成派生类对象析构不完全。...如果声明了,触发 派生类 ,基类 正确析构顺序。

70930
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    面试题:基类的析构函数为何要声明为虚函数?

    基类的析构函数到底是否需要声明为虚函数取决于你是否会使用继承体系。 当使用继承时,如果一个基类指针指向了一个派生类对象,当对指针进行 delete 操作时,应该同时调用基类和派生类的析构函数。...如果基类的析构函数不是虚拟函数,则运行时不能确认要调用哪个析构函数。如果它是虚拟的,则始终将调用最实际对象的析构函数。...在 main() 函数中,通过基类指针创建一个 Dog 类型的对象,然后删除指针。...由于 Animal 的析构函数不是虚拟的,所以仅调用了基类的析构函数: Animal constructor Dog constructor Animal destructor 可以看到,Dog 类的析构函数没有被调用...总结 在使用继承时,应该将基类的析构函数声明为虚函数,这样可以确保在运行时删除派生类对象时同时调用基类和派生类的析构函数。否则运行时不能确认要调用哪个析构函数,并且可能导致内存泄漏和其他问题。

    4700

    c++学习笔记4,调用派生类的顺序构造和析构函数(一个)

    大家好,又见面了,我是全栈君 测试源代码: //測试派生类的构造函数的调用顺序何时调用 //Fedora20 gcc version=4.8.2 #include using namespace..."<<endl; A *a2=new A; //仅仅有在new 一个对象的时候才会调用基类的构造函数 cout调用基类的构造函数"<<endl; A *a3=&a; B b; } 输出为: 能够看到,在创建派生类的对象的时候,首先调用的是基类中的构造函数,然后才是调用派生类自己的构造函数...而在析构的时候,顺序则刚好相反,先调用派生类的析构函数,然后才是调用基类的构造函数。这是由于对象创建时候对象存放在堆栈中的原因。(new 的对象尽管是存在堆中,可是在堆栈中依旧存放其堆中的地址,因此。...析构的时候也是一样) 那么,创建其对象的数组时:A a[2],是否会调用其构造函数呢。这是肯定的。

    71310

    反常识:为什么虚函数在构造和析构时并不“虚”?

    三个函数 本题从字面中可以看到涉及到三个函数,分别是: 构造函数:构造函数是用来初始化对象的,它会在对象创建时被调用。 析构函数:析构函数是用于清理对象的,它会在对象销毁时被调用。...虚函数:虚函数是由virtual关键字修饰的在基类中定义(通常情况下需要)在派生类中重写的函数。...所以虚函数通常涉及到基类派生类,涉及到重写;同时结合构造函数和析构函数,所以本题中的虚函数调用可细分为如下的8种情况(见下图)。...实际到考察的是父类构造函数、父类析构函数中调用的虚函数两种情况下,函数的执行是否符合预期。要回答这两个问题,需要从继承时父类和派生类的构造函数、析构函数的执行顺序,多态的实现原理两个角度回答。...也就是说:,父类构造函数执行时,子类对象还未初始化;而调用到父类的析构函数时,对象的子类部分已经被销毁。

    7810

    面试题:什么是虚函数?

    面试题:什么是虚函数? 在 C++ 中,虚函数是一种特殊的成员函数,它允许在基类中使用 virtual 关键字声明,在派生类中进行重写,并且可以通过基类指针或引用调用派生类的成员函数。...调用虚函数 虚函数通过基类指针或引用来调用派生类的成员函数。...虚析构函数 还有一个非常重要的内容:如果你在具有派生类的基类析构函数中不是将析构函数声明为虚拟,则不会删除具有派生类对象的基类指针的派生类对象。...此时,Animal 的析构函数不是虚函数,所以当使用的时候调用是 Animal 的析构函数。因此,如果您计划通过一个基类指针删除派生的对象,请将基类的析构函数声明为虚拟的。...总结 虚函数是 C++ 中实现多态的重要机制之一,它允许在基类中声明函数为虚拟函数,在派生类中进行重写,并且可以通过基类指针或引用调用派生类的成员函数。

    6300

    什么时候使用虚析构函数

    问题 什么时候该定义虚析构函数,为什么要这么做? 回答 当你通过一个基类指针去删除(delete)派生对象的时候,虚析构函数就很用了。...Base 的析构函数定义为虚(virtual)。...输出如下: Base Constructor Called Derived constructor called Base Destructor called 我们发现派生类的析构函数并没有调用,这是有问题的...都无需定义基类虚拟析构函数,否则你就应该定义为虚, 这个基类没有派生类 不在堆(heap)内存实例化 没有指向派生类的基类指针或引用 对于 1,还是很常见的,有的时候我们只是单纯的写一个类,并没有派生它的打算...对于 3,基本上也不太可能,派生类的存在基本上都会用到它的基类指针和引用。

    91520

    解锁C++多态的魔力:灵活与高效的编码艺术(上)

    2.1.1 为什么需要基类指针或引用 在C++中,如果直接使用派生类对象,即使它重写了基类的虚函数,编译器仍然会使用静态绑定,即在编译时确定调用的函数版本。...2.4 虚析构函数(Virtual Destructor)的重写 在C++中,虚析构函数(Virtual Destructor)是一种特殊的析构函数,通过在基类中将析构函数声明为虚函数,可以确保在通过基类指针删除派生类对象时...当基类指针指向派生类对象时,如果删除对象时基类的析构函数不是虚函数,那么调用的仅仅是基类的析构函数,而不会调用派生类的析构函数。这样,派生类中分配的资源就无法释放,导致内存泄漏或其他资源管理问题。...2.4.3 虚析构函数的注意事项 虚析构函数的必要性:任何含有虚函数的基类都应定义虚析构函数,以确保派生类对象通过基类指针删除时能够正确析构。...() {} // 提供析构函数体 总结 虚析构函数确保通过基类指针删除派生类对象时正确调用派生类的析构函数,避免内存泄漏。

    15710

    C++继承

    基类private成员在派生类中无论以什么方式继承都是不可见的。这里的不可见是指基类的私 有成员还是被继承到了派生类对象中,但是语法上限制派生类对象不管在类里面还是类外面都不能去访问它。 2....接着,那基类和派生类对象赋值转换是什么意思呢? 我们可以把子类赋值给父类(当然是在公有继承的情况下) 派生类对象 可以赋值给 基类的对象 / 基类的指针 / 基类的引用。...(返回值和参数可以不相同) 四、派生类的默认成员函数 1、默认构造函数 派生类的成员:内置类型和自定义类型分别处理 基类的成员:调用父类的构造函数 如果基类没有默认的构造函数,则必须在派生类构造函数的初始化列表阶段显示调用...注意子类不能帮父类初始化,父类只能调用自己的构造函数,不能让子类去“帮忙” 注意构造函数调用顺序是先父后子,因为初始化列表初始化的顺序跟出现的顺序无关,跟声明的顺序有关 2、析构函数 子类的析构函数和父类的析构函数构成隐藏关系...为了保证先调用子类的析构函数,父亲的析构会在子类析构后自动调用。 构造:先父后子 析构:先子后父 为什么析构函数是先子后父呢?

    6910

    【C++】从零开始认识继承

    那么我们很自然的想到在派生类析构函数中调用基类析构: 但是报错了??? 因为子类的析构也会隐藏父类的析构!!!...其实,派生类的析构函数会在被调用完成后自动调用基类的析构函数清理基类成员。因为这样才能保证派生类对象先清理派生类成员再清理基类成员的顺序。...所以我们不必在派生类的析构函数中进行调用基类的析构函数,不然就会重复释放同一块空间,导致报错! 因为析构必须要按先子后父的顺序,父亲没了何谈子呢?...派生类的析构函数会在被调用完成后自动调用基类的析构函数清理基类成员。因为这样才能保证派生类对象先清理派生类成员再清理基类成员的顺序。 派生类对象初始化先调用基类构造再调派生类构造。...派生类对象析构清理先调用派生类析构再调基类的析构。 因为后续一些场景析构函数需要构成重写,重写的条件之一是函数名相同(这个我们后面会讲解)。

    8110

    【c++】全面理解C++多态:虚函数表深度剖析与实践应用

    (基类与派生类析构函数的名字不同) 如果基类的析构函数为虚函数,此时派生类析构函数只要定义,无论是否加virtual关键字,都与基类的析构函数构成重写,虽然基类与派生类析构函数名字不同。...,如果基类的析构函数没有被声明为虚拟的(virtual),将会发生对象的不完全析构。...这意味着只有基类的析构代码会被执行,而派生类的析构逻辑不会调用,可能导致资源泄露或其他问题。...其中 p2 是一个基类 Person 类型的指针,指向一个 Student 对象),Student 的析构函数首先会被调用(子类),然后是 Person 的析构函数(基类) 因此,重写基类的虚拟析构函数确保了当通过基类指向派生类对象的指针进行...delete 操作时,能够按照正确的顺序调用派生类和基类的析构函数 派生类可以不写virtual class Person { public: virtual void BuyTicket() {

    33800

    C++学习笔记 -- 虚析构函数与纯虚析构函数

    开始学C++了,所以又重拾以前学习过的相关概念… 析构函数是当一个对象的生命周期结束时,会自动执行析构函数。...虚函数表的作用是用来实现多态,但同时也带来了执行效率和额外内存空间的增加。 再来看虚析构函数,它所存在的意义:基类的指针指向派生类对象,用基类的指针删除派生类对象。...派生类继承自基类,那么基类就只会存在于派生类中,直到派生类调用析构函数后。...所以这就矛盾了,所以派生类的析构函数会先被调用,基类的析构函数再被调用。...… B::f() A::ff() //定义指向基类对象的指针a,当调用f()方法时,因为f为虚函数,所以调用了派生类的f(),输出B::f(); 参考: 详解C++中的纯虚函数(虚函数区别)&多态性以及实例应用

    1.7K40

    C++纯虚函数与抽象类

    在继承体系中,构造的顺序就是从基类到派生类,其目的就在于确保对象能够成功地构建。构造函数同时承担着虚函数表的建立,如果它本身都是虚函数的话,又如何确保虚函数表的成功构建呢?...1.2虚析构函数 在类的继承中,基类的析构函数一般都是虚函数。当基类中有虚函数的时候,析构函数也要定义为虚析构函数。...如果不定义虚析构函数,当删除一个指向派生类对象的指针时,会调用基类的析构函数,派生类的析构函数未被调用,造成内存泄露。...虚析构函数工作的方式是:最底层的派生类的析构函数最先被调用,然后各个基类的析构函数被调用。这样,当删除指向派生类的指针时,就会首先调用派生类的析构函数,不会有内存泄露的问题了。...一般情况下,如果类中没有虚函数,就不用去声明虚析构函数。当且仅当类里包含至少一个虚函数的时候才去声明虚析构函数。只有当一个类被用来作为基类的时候,才有必要将析构函数写成虚函数。

    1.5K20

    【C++修炼之路】15.C++继承

    四.派生类的默认成员函数 在最初的类和对象章节,讲过默认生成的四个成员函数:构造函数、拷贝构造函数、析构函数、赋值运算符重载。...因此,析构这里也需要与前三部分的不同:析构不需要像前三个一样显示调用对应的基类的析构函数,而是会自动生成基类的析构函数。因此,不必在派生类的析构函数中调用基类的析构,而是会自动生成。...发现顺序: 构造: 基类先构造,派生类后构造。 析构: 派生类先析构,基类后析构。 4.5 总结 派生类的构造函数必须调用基类的构造函数初始化基类的那一部分成员。...派生类的operator=必须要调用基类的operator=完成基类的复制。 派生类的析构函数会在被调用完成后自动调用基类的析构函数清理基类成员。...因为这样才能保证派生类对象先清理派生类成员再清理基类成员的顺序。 派生类对象初始化先调用基类构造再调派生类构造。 派生类对象析构清理先调用派生类析构再调基类的析构。

    55700

    掌握了多态的特性,写英雄联盟的代码更少啦!

    在构造函数和析构函数中调用「虚函数」,不是多态。 编译时即可确定,调用的函数是自己的类或基类中定义的函数,不会等到运行时才决定调用自己的还是派生类的函数。 我们看如下的代码例子,来说明: ?...---- — 5 — 虚析构函数 析构函数是在删除对象或退出程序的时候,自动调用的函数,其目的是做一些资源释放。...那么在多态的情景下,通过基类的指针删除派生类对象时,通常情况下只调用基类的析构函数,这就会存在派生类对象的析构函数没有调用到,存在资源泄露的情况。...pa指针对象时,B 类的析构函数没有被调用。...解决办法:把基类的析构函数声明为virtual 派生类的析构函数可以 virtual 不进行声明; 通过基类的指针删除派生类对象时,首先调用派生类的析构函数,然后调用基类的析构函数,还是遵循「先构造,后虚构

    53010

    【C++】继承 ⑧ ( 继承 + 组合 模式的类对象 构造函数 和 析构函数 调用规则 )

    一、继承 + 组合 模式的类对象 构造函数和析构函数调用规则 1、场景说明 如果一个类 既 继承了 基类 , 又 在类中 维护了一个 其它类型 的 成员变量 , 那么 该类 的 构造 与 析构 , 就需要涉及到...类 本身 的 构造函数 和 析构函数 , 父类 的 构造函数 和 析构函数 , 类 成员变量 的 构造函数 和 析构函数 ; 2、调用规则 在 继承 + 组合 的情况下 , 构造函数 与 析构函数 调用规则如下...自身定义的 构造函数 ; 析构函数 : 自身 -> 成员 -> 父类 ; 首先 , 调用 自己 析构函数 ; 自身定义的 析构函数 ; 然后 , 调用 成员 析构函数 ; 也就是 成员变量 类型的...析构函数调用" << endl; } public: int z; D d; }; 可根据下面的调用规则 , 分析出 C 类对象中 , 涉及到的 父类构造/析构函数 , 自身构造/析构函数...; 然后分析 析构函数 调用顺序 ; C 析构函数 , 是 自身构造函数 ; D 析构函数 , 是 成员构造函数 ; A 和 B 的析构函数 , 是 父类构造函数 ; 析构函数的调用顺序为 : 自身

    20510

    Cpp虚函数相关知识点

    当子类child继承base的时候,创建一个base类的指针,让它 指向子类对象,这时候用基类指针调用print(),此时会自动判断,然后调用子类中的函数, 如果基类不加virtual,基类指针就直接调用基类的...可以看这一篇文章探索C++虚函数在g++中的实现,讲的很详细。 析构函数为什么是虚函数 明白了虚函数的特点,这个问题就不难了。...当基类指针指向子类对象的时候,在对象使用完毕需要释放时,肯定需要调用子类对象的析构函数呀,所以这种情况下析构函数也得是虚函数。...也可以看这段话: 基类指针可以指向派生类的对象(多态性),如果删除该指针delete []p; 就会调用该指针指向的派生类析构函数,而派生类的析构函数又自动调用 基类的析构函数,这样整个派生类的对象完全被释放...如果析构函数不被声明成虚函数,则编译器实施静态绑定, 在删除基类指针时,只会调用基类的析构函数而不调用派生类析构函数, 这样就会造成派生类对象析构不完全。所以,将析构函数 声明为虚函数是十分必要的。

    39920

    C++:继承与派生

    派生类的构造函数必须调用基类的构造函数初始化基类的那一部分成员。如果基类没有默认的构造函数,则必须在派生类构造函数的初始化列表阶段显示调用。 2....派生类的拷贝构造函数必须调用基类的拷贝构造完成基类的拷贝初始化。 3. 派生类的operator=必须要调用基类的operator=完成基类的复制。...4、派生类的析构函数会在被调用完成后自动调用基类的析构函数清理基类成员。因为这样才能 保证派生类对象先清理派生类成员再清理基类成员的顺序。 5....派生类对象初始化先调用基类构造再调派生类构造,派生类对象析构清理先调用派生类析构再调基类的析构。...,会自定调用父类析构函数,保证先析构子再析构父 protected: int _num; //学号 }; 思考: 1、既然我们知道了怎么显式写,但是真的有必要吗??

    18610

    【C++进阶】多态,这样学才够清楚

    ,delete对象调用析构函数才能构成多态,才能保证p1和p2指向的对象正确的调用析构函数 1.2.4 为什么要重写析构函数 普通情况下析构子类对象: class Person { public: ~...多态删除:在使用多态时(即基类指针指向派生类对象),如果通过基类指针删除派生类对象,并且基类析构函数没有被声明为虚函数,那么只会调用基类的析构函数,而不会调用派生类的析构函数。...这会导致派生类对象中的资源没有被正确释放,从而造成内存泄漏等问题。因此,在多态基类中,通常会将析构函数声明为虚函数,并可能需要在派生类中重写它以执行特定的清理工作。...需要注意的是,即使你不需要在派生类的析构函数中执行任何特定的清理工作,如果你打算通过基类指针来删除派生类对象,并且想要确保派生类对象中的资源被正确释放,你也应该将基类的析构函数声明为虚函数。...这样做可以确保当通过基类指针删除派生类对象时,派生类的析构函数也会被调用。

    7710

    【C++ 进阶】继承

    class时默认的继承方式是private; 使用struct时默认的继承方式是public; 三.派生类和基类之间的赋值转换  1.派生类对象 可以赋值给 基类的对象 / 基类的指针 / 基类的引用...但是必须是基类的指针是指向派生类对象时才是安全的; 四.隐藏(重定义) 1.子类和父类中,只要函数名相同就构成隐藏; 2.成员名相同也构成隐藏; 3.在子类成员函数中,可以使用 基类::基类成员...五.派生类中的默认成员函数 1.构造函数  派生类必须先自动调用基类的默认构造(初始化基类的那一部分成员),如果基类没有默     认构造,就要在派生类的初始化列表阶段显式调用基类的构造函数,然后派生类调用自己...4.析构函数    销毁对象时,会先调用派生类的析构函数,然后再自动调用基类的析构函数,这样就保证     了析构的顺序(即先子后父);    如果不是这个顺序,一个成员可能会析构两次,就会导致程序崩溃...,在调用完后,编译器又会自动调用一次父类的析构函数, //导致父类成员_a析构了两次,从而程序崩溃 } int* _b = new int; }; int

    14210
    领券