精华内容
下载资源
问答
  • 把基类析构函数定义为虚函数,在调用析构函数时,会根据指向的对象类型到它的虚函数表中找到对应的虚函数,此时找到的是派生类的析构函数,因此调用该析构函数;而调用派生类析构函数之后会再调用基类的析构函数,...

    首先,构造函数是不能为虚函数的
    在这里插入图片描述

    调用构造函数后, 才能生成一个对象。 假设构造函数是虚函数, 虚函数存在于虚函数表中, 而去找虚函数表又需要虚函数表指针, 而虚函数表指针又存在于对象中, 这样就矛盾了: 都没有生成对象, 哪有什么虚函数表指针呢?
    在这里插入图片描述
    那么问题又来了,析构函数可以是虚函数吗?
    答:可以
    把基类析构函数定义为虚函数,在调用析构函数时,会根据指向的对象类型到它的虚函数表中找到对应的虚函数,此时找到的是派生类的析构函数,因此调用该析构函数;而调用派生类析构函数之后会再调用基类的析构函数,因此不会导致内存泄漏。

    展开全文
  • C++ 基础知识(二)——多态与虚函数题目C 基础知识二多态与虚函数 题目 C对象模型 程序模型 抽象数据类型模型abstruct data type modelADT ...问题那么构造函数可以定义为虚函数吗 参考资料C++对象模型在

    C++ 基础知识(二)——多态与虚函数

    题目

    C++对象模型

    在介绍多态和虚函数之前,我们先来谈谈C++的对象模型(或者说编程范式)是什么,或者C++语言的复杂性在哪里。
    C++不同于面向过程语言C,也不同于别的面向对象语言,如Java,Python等,是因为C++中有多种对象模型。

    1.程序模型

    这种模型就像C语言一样,是一种面向过程的模型。例如:

    char boy[] = "Danny";
    char *p_son;
    ...
    p_son = (char *)malloc(strlen(boy) + 1);
    strcpy(p_son, boy);
    if(!strcpy(p_son, boy)
    {
        take_to_disneyland(boy);
    }

    2.抽象数据类型模型(abstruct data type model,ADT)

    此模型相当于现实中的对象封装起来,将属性和行为联系在一起。对ADT来说,你就要确切地知道它是什么,什么类型,有具体的内存空间。比如一个老虎,是实实在在存在的对象,属于抽象数据类型模型,但是我们通常说的老虎是动物,所以设计类的时候,通常设计一个类动物(没有任何数据成员,因为不存在),然后让老虎继承。由于动物是一个抽象概念,没有实实在在存在,所以不属于抽象对象类型模型。而上面的模型则是我们后面说的面向对象模型。所以,继承在ADT里就没有多少语义了,因为所有的对象都必须实实在在存在(分配内存)。

    std::string daughter;
    daughter.size();
    ...

    像代码中的对象daughter,它在内存中已经分配有空间,实实在在存在,且类型就是string。注意与面向对象模型区分开来,接下来我会讲到。

    3.面向对象模型(object-oriented model)

    面向对象模型就是我们所接触最多的模型了。有抽象特性,继承特性,多态特性。

    Animal
    {
    public:
        virtual void run() = 0;
    };
    Tiger
    {
    public:
        virtual void run() { std::cout << "Tiger::run()" << std::endl; }
    };
    Dog
    {
    public:
        virtual void run() { std::cout << "Dog::run()" << std::endl; }
    };
    int main()
    {
        Animal *animal = new Tiger;
        father->run();  //打印Tiger::g()
        animal = new Dog;
        father->run();  //打印Dog::g()
        return 0;
    }

    通过指针+虚函数来实现多态特性。我们并不知道该指针所指的具体类型是什么(比如Animal *animal),它可能指向Tiger对象,也可能指向Dog对象,而且动物本身并不存在。
    那多态究竟是什么呢?其实就是根据你父类指针所指的对象不同,调用不同对象对该函数的执行。通俗的说,由于父类(动物)是一个抽象类,定义了该类的行为(跑),但是子类(老虎,狗)继承父类,虽然都有这样一个行为(都会跑),但是具体的方式是不一样的(狗跑,和老虎跑是不一样的),这种父类中的行为在子类中表现不一样的情况就叫多态。

    4.泛型编程

    就是C++中的模板。

    template<typename type>
    class Test
    {
        type x;
    };

    模板具体是什么,请google,我这里就不多说了。

    5.总结

    C++由于支持多种编程范式,或者说拥有多种对象模型,所以我们一般称C++为基于对象语言,而不是面向对象语言。C++不是像其他语言一样,只有一种编程范式,C语言面向过程,Java,Python面向对象模型。所以才造成语言的复杂性及学习的陡峭性。

    至于使用一种编程范式更好呢,还是像C++这样使用多种编程范式结合编程更好呢,这个就看具体的应用场景了,没有绝对的优劣。

    多态与虚函数的关系

    那么多态与虚函数是什么关系呢?
    其实就是多态是面向对象范式的特性,而这种特性通过C++语言的虚函数来实现(在成员函数声明前加virtual)。

    而继承自该类的子类,哪怕函数声明没有virtual,但只要函数接口与父类完全一样(函数名,参数列表,返回值类型),编译器会父类继承该函数的virtual属性,该函数则为虚函数。

    虚函数内部机制

    1.对于类

    对于定义有虚函数的类来说,编译器会为该类生成一个虚函数表(virtual table),该表中按照声明顺序保存有该类所有虚函数的地址(包括继承父类,自己没有额外实现的;自己重新实现父类的虚函数和自己新定义的)。

    2.对于对象

    对于含有虚函数的类创建的对象,则会在为对象申请空间时,一般编译器会在对象开头额外分配4个字节的空间,来存储该类虚函数表指针(vptr),并在构造函数中对vptr进行初始化。这样每次使用父类指针调用虚函数时,会根据你具体指向对象的不同,通过vptr来调用该对象的虚函数,从而实现了可以通过父类指针指向不同的子类对象(vptr不同),调用虚函数来产生不同的行为。

    备注:对于虚函数的图文讲解,请参考陈浩的博客:C++虚函数解析 ,我觉得讲的更通俗易懂。我更多的是从文字来对此进行总结,可以看完他的该文章回头在看我的这篇文章,可能会更好一些。

    虚函数使用的场景

    1.普通场景

    最基本的用法就是,根据你具体设计的类,同一个行为在不同的子类中会有不同的动作时,使用虚函数。

    2.析构函数

    析构函数通常定义为虚函数,这样就不会发生下面的行为。

    class Test
    {
    int x;
    };
    class TestSon : public Test
    {
    public:
        TestSon(int num) { x = new char[num]; }
        ~TestSon() { delete x; }
    private:
        char *x;
    };
    
    int main()
    {
        Test * test = new TestSon(5);
        return 0;
    }

    当主函数执行完成后,会调用Test类的析构函数,但是你其实创建的是一个子类对象,会造成子类的开辟空间没有释放掉(因为子类的析构函数是有关紧要的,不执行的话,就无法释放new开辟的内存)。
    如果把析构函数定义为虚函数时,由于父类指向的是子类对象,则会去调用子类的析构函数,不会出现问题。

    问题:那么构造函数可以定义为虚函数吗?

    C++中是不可以的。

    • 根据C++的语法来说,构造函数是对创建的对象进行初始化的,而虚函数又是必须是对象创建出来之后对不同的对象执行不同的行为。对象还没有创建完成时,你此时并不知道此时这个构造过程中是构造链中父类的构造函数还是子类的构造函数,对象还没有创建,那么此时执行的多态必然是错误的。

    • 从语言的内部原理来说,C++创建对象时,是在构造函数中初始化虚表指针(vptr)的,你在调用构造函数之前,vptr是没有值的,那怎么根据这个vptr来确定你要执行的函数的指针的,这也是矛盾的。,所以这个vptr是不是你创建对象的vptr呢,这个是未知的。

    那既然C++是不可以的,那么谁可以呢,Delphi的构造函数是可以是虚函数

    参考资料

    [1] 深度探索C++对象模型
    [2] 陈浩的博客:C++虚函数解析地址 http://blog.csdn.net/haoel/article/details/1948051

    展开全文
  • C++ 虚函数

    2015-09-01 17:07:00
    3、析构函数可以定义虚函数吗? 可以,虚析构函数是允许的,但是要注意,只有在作为基类时,我们才需要将析构函数写成虚函数。 4、虚拟机制与构造函数 在类的构造函数中,虚拟机制不会发生作用。因为,基类的构造...

    1、什么是虚函数?

    在类中使用virtual关键字声明的函数就叫虚函数。

    2、为什么使用虚函数?

    因为使用虚函数以后,集成类可以重载基类中的成员函数。

    3、析构函数可以定义成虚函数吗?

    可以,虚析构函数是允许的,但是要注意,只有在作为基类时,我们才需要将析构函数写成虚函数。

    4、虚拟机制与构造函数

    在类的构造函数中,虚拟机制不会发生作用。因为,基类的构造函数在派生类构造函数之前执行,当基类构造函数运行时,派生类数据成员还没有被初始化。

    引用和指针对象 实现多态。。。

     

    5、类继承最重要的特性是可用基类的指针或引用来操作派生类

    转载于:https://www.cnblogs.com/audi-car/p/4776214.html

    展开全文
  • 我们知道虚函数表在编译时期被确定,虚表指针vptr在程序run time时在类对象构造函数执行期间被初始化,那它可能在什么情况下会被修改呢? 我现在知道在派生类对象构造时其会被修改;那除了这种情况之外还有什么场景...
  • 腾讯一面到三面一共花了一周,目前正在等待HR面。在面试准备的过程中,牛客网上各位...3.构造函数可以定义为虚函数吗 4.stl里vector内存如何管理 5.vector中迭代器是否会失效? 6.函数参数入栈顺序,函数栈帧内存的...


     

    腾讯一面到三面一共花了一周,目前正在等待HR面。在面试准备的过程中,牛客网上各位前辈的面经给我提供了很大帮助,今天我把自己的面试经历分享给大家,希望能对正在或者日后找实习和工作的各位有所帮助。

     

    一面(1h)

    项目(20min)

    算法题反转链表(10min)

    基础(30min)

    C++
    1.基类的虚构函数为什么定义为虚函数
    2.虚函数原理
    3.构造函数可以定义为虚函数吗
    4.stl里vector内存如何管理
    5.vector中迭代器是否会失效?
    6.函数参数入栈顺序,函数栈帧内存的分布(这个不会)
    7.字节对齐为什么可以提高访问速度?


    linux
    1.查看进程内存,cpu负载用什么命令?
    2.free里面空闲内存是实际的空闲内存?(不是的,已使用的内存有未使用的部分,因为有swap区域等)


    操作系统
    1.僵尸进程如何产生的?
    2.如果进程产生内存泄漏,如何定位问题?

     

    数据库

    1.mysql里假设有1张表,其中有a、b、c三个字段,做了联合索引,现在用a、c查询 where select XXX where a = XXX, c = XXX

    (mysql这块没学过,后面就没问mysql相关问题)


    网络
    1.TCP四次挥手能不能改为三次挥手?服务器没有数据发送,是否可以改为三次挥手?
    2.TCP什么情况会出现粘包?
    3.如何实现可靠的UDP?
    4.HTTPS的握手流程
    5.常用负载均衡的算法


    算法
    1.快排的时间复杂度?何时退化成最慢?
    2.10万个无序的int32的数字,如何找出中位数?

     

    二面(1h30min)

    二面所有的问题都是从我做的项目引申出来的,主要是网络、redis和分布式这块(1h)

    1.有什么负载均衡算法


    2.ip_hash算法中,某个节点挂掉,负载数量减少,如何优化?


    3.HTTP如何追踪客户端,例如登录时缓存用户名和密码?


    4.cookie在HTTP报文中如何使用?


    5.HTTP会话相关信息保存在哪里?


    6.HTTP中chunked编码了解吗?(不会)


    7.介绍HTTPS(怎么又是你 😂)


    8.CA证书中包含哪些内容?(还是不会)


    9.客户端收到CA证书如何校验其合法性,并验证其是否被篡改?

     


    10.HTTPS中公钥如何防止被别人篡改?如果有中间人攻击呢?


    11.CA证书给了什么东西到服务器端?(依然不会)


    12.数字签名如何校验?


    13.CA机构是如何用自己的私钥做数字签名?


    14.accept函数返回的时候发生在三次握手的哪个阶段?

     

    场景设计题(30min)
    1.有五台服务器,都运行同样的程序,如何生成全局唯一的ID?有哪些方案?如何优化?


    2.分布式节点的通讯方式?这五台服务器的例子是否需要分为主、从服务器?


    3.介绍主服务器的备份机制

     

    4.主服务器使用了一个id,但未同步给其他从服务器,然后主服务器宕掉了,而从服务器可能相同的id,如何解决?


    5.如果主服务器提前发送通知,中间出现丢包,从服务器未收到,怎么解决?或者主服务器如何得知从服务器是否收到通知?可以用SYN、ACK交互的方式解决吗?

     

    三面(1h)

    基础(30min)

    C++

    1.介绍多态机制
    2.一个没有任何数据成员的类实例化之后占用空间大小是多少?
    3.new出来的指针用free函数释放可以吗?


    网络

    1.IO多路复用函数select、poll、epoll区别,为什么用epoll?
    2.epoll的触发模型?
    3.TCP中time_wait状态第几次挥手出现,time_wait状态太多会有什么问题?

    4 .加密算法具体了解哪些?
    5.HTTPS建立连接的过程?(怎么老是你😂)

     

    Linux
    1.linux查看当前有哪些网络处于监听状态用什么命令?网络抓包呢?
    2.linux查看系统负载用什么命令?
    3.linux查看系统用了哪些信号量用什么命令?
    4.linux查看系统目前分配了哪些共享内存用什么命令?
    5.linux取文件倒数十行用什么命令?
    6.两个文本文件里面,每一行都是一个整数,求在A文件里但不在B文件里的那些数字用shell脚本可以做吗?

    (这个不会)
    7.awk听说过吗?用过吗?大概介绍一下

     

    数据库
    1.redis持久化怎么做的?


    编程题(30min)
    1. leetcode 647 回文子串
    2. leetcode 319 灯泡开关
     

    总结

    三轮整体面试体验挺好的,面试官都很nice。感觉腾讯这边比较侧重网络相关的知识,问的比较细致深入,尤其是二面的时候,面试官多次直击我的知识盲区 😂。还有就是感觉腾讯面试的问题也会侧重对知识点的融会贯通和综合分析,例如二面中的场景分析题,答案是开放的,但面试官会根据的你的回答提出可能的缺陷,引导你不断地优化。

    还有一点必须吐槽,三轮面试每次都问HTTPS的连接过程,这个问题的考察频率这么高吗,有点神奇😂。

    预祝各位找实习和工作的同学早日拿到心仪的offer!''

     

     

     

    展开全文
  • C++高频知识总结P4

    2020-09-03 15:34:49
    构造函数可以虚函数吗?析构函数可以是虚函数吗?为什么析构函数要定义为虚函数?2.构造函数或者析构函数中调用虚函数会怎样?3.声明和定义的区别?4.指针函数和函数指针?5.指针常量?常量指针?6.深拷贝与浅拷贝...
  • 父类的析构函数为什么要定义为虚函数? 内联函数,构造函数,静态成员函数可以虚函数吗构造函数中可以调用虚函数吗? 为什么需要虚继承?虚继承实现原理解析, C ++内存分配机制 指针 迭代器与普通指针有什么...
  • C++学习笔记07

    2017-09-05 20:50:00
    1:子类析构时要调用父类的析构函数吗? 析构函数调用的次序是先派生类的析构后基类的析构,也就是说在基类的的析构调用的时候,派生类的信息已经全部...2:基于构造函数的特点,不能将构造函数定义为虚函数,但可以
  • 18多态

    2017-06-01 14:10:52
    多态多态 问题引出 解决方案 工程意义 成立条件 理论基础 本质剖析 1 多态实现原理 ...6 类的每个成员函数是否都可以声明为虚函数为什么 7 构造函数中调用虚函数能实现多态吗为什么 8 虚函数表指针VPTR被编译
  • C++秋招记录(二)一、虚函数1、继承下的虚函数表2、virtual继承和virtual函数3、virtual函数的优缺点4、构造函数为什么不能是virtual?5、如何定义clone来实现类似virtual constructor的功能?6、析构函数什么要是...
  • 构造函数可以虚函数吗? 构造函数、析构函数、虚函数可否内联,有何意义? new delete 与 malloc free区别? 空类 sizeof 为什么是1? 4个显示强制类型转换? 为什么一般要定义析构函数为虚析构函数? 静态...
  • C++面试题. 小米社招

    千次阅读 2020-06-03 11:34:34
    C++构造函数可以虚函数吗?为什么? C++析构函数可以是虚函数吗?为什么要将析构函数设置为虚函数? C++如何实现多态?虚表指针是什么时候被初始化的?实例化一个对象需要那几个阶段?(三个) C++偏特化? ...
  • C#面经_全职

    2021-06-11 23:17:00
    8、析构函数可以定义为虚函数吗? 9、构造函数的作用? 10、用过或了解的设计模式? 11、web如何获取客户端的数据? 12、程序崩溃或异常怎么处理? 13、内存中不是非托管内存崩溃了,调用第三方库导致内存崩溃
  • 零起点学通C++多媒体范例教学代码

    热门讨论 2010-11-30 09:35:13
    14.1.5 将数组的下标定义为常量 14.1.6 手动操作数组元素 14.1.7 数组的初始化 14.2 数组的用途 14.2.1 求平均考试成绩 14.2.2 兔子繁殖问题 14.2.3 数字排序问题 14.3 数组在内存中的分布 14.4.输出数组名 14.5 ...
  • 14.1.5 将数组的下标定义为常量 14.1.6 手动操作数组元素 14.1.7 数组的初始化 14.2 数组的用途 14.2.1 求平均考试成绩 14.2.2 兔子繁殖问题 14.2.3 数字排序问题 14.3 数组在内存中的分布 14.4.输出数组名 ...
  • 14.1.5 将数组的下标定义为常量 230 14.1.6 手动操作数组元素 231 14.1.7 数组的初始化 232 14.2 数组的用途 233 14.2.1 求平均考试成绩 233 14.2.2 兔子繁殖问题 235 14.2.3 数字排序问题 237 14.3 数组在...
  • 10.3.1 声明和定义构造函数 10.3.2 使用构造函数 10.3.3 默认构造函数 10.3.4 析构函数 10.3.5 改进Stock类 10.3.6 构造函数和析构函数小结 10.4 this指针 10.5 对象数组 10.6 类作用域 10.6.1 作用域类...
  • 摩托罗拉C++面试题

    2009-08-19 19:52:41
    构造函数不能为虚函数,要构造一个对象,必须清楚地知道要构造什么,否则无法构造一个对象。 析构函数可以为纯虚函数。 10,拷贝构造函数相关问题,深拷贝,浅拷贝,临时对象等。 深拷贝意味着拷贝了资源和指针,而...
  • MFC的程序框架剖析

    2015-03-05 09:53:19
    对了,还有一点要说明的是:pTemplate是一个CDocTemplate的指针,但接下来程序为什么会进入到CSingleDocTemplate::OpenDocumentFile的函数体内呢,这是因为CDocTemplate类中的OpenDocumentFile函数定义为纯虚函数...
  • “,然后再再深入一点,“如果把析构函数标记为虚函数呢?”,要准确得出这些答案就得考查我们深厚的内力了。其实,我还是蛮喜欢这样写书风格的,层层深入,很能考查读者对某个知识点的掌握程度,然后再跟着作者再往...
  • 面试题209 基类中有一个虚函数,子类还需要申明virtual吗 面试题210 C++的类有什么优点 面试题211 如何实现多态?父类和子类的继承关系如何 面试题212 什么要引入抽象基类和纯虚函数(摩托罗拉笔试 题) 面试题...
  • 21天学通C++ (中文第五版)

    热门讨论 2010-06-23 16:57:03
    12.5.1 虚函数的工作原理 12.5.2 通过基类指针访问派生类的方法 12.5.3 切除 12.5.4 创建虚析构函数 12.5.5 虚复制构造函数 12.5.6 使用虚方法的代价 12.6 小结 12.7 问与答 12.8 作业 12.8.1 测验 12.8.2...
  • C++程序员面试宝典

    热门讨论 2013-04-01 13:36:19
    面试题107 构造函数与析构函数的调用时机 116 10.2 访问控制 118 面试题108 有哪几种继承方式 118 面试题109 继承时访问级别如何变化 120 10.3 继承时的类作用域 121 面试题110 什么时候发生函数覆盖 121 面试题111 ...
  • const定义的常量是有类型的,所以在使用它们时编译器可以查错;而且,这些变量在调试时仍然是可见的。 2-5 请写出C++语句声明一个常量PI,值3.1416;再声明一个浮点型变量a,把PI的值赋给a。 解: const float PI...
  • 面试题8:构造函数能否为虚函数 面试题9:简述子类与父类的析构、构造函数的调用顺序 面试题10:编写类String 的构造函数、析构函数和赋值函数 8.4 拷贝构造函数 面试题11:谈谈对拷贝构造函数和赋值运算符的认识 ...
  • 14.4.1 构造函数和析构函数的使用 325 14.4.2 auto_ptr 326 14.4.3 告诫 328 14.4.4 异常和new 328 14.4.5 资源耗尽 329 14.4.6 构造函数里的异常 331 14.4.7 析构函数里的异常 332 14.5 不是错误的异常 333 ...
  • 14.4.1 构造函数和析构函数的使用 325 14.4.2 auto_ptr 326 14.4.3 告诫 328 14.4.4 异常和new 328 14.4.5 资源耗尽 329 14.4.6 构造函数里的异常 331 14.4.7 析构函数里的异常 332 14.5 不是错误的异常 333 ...
  • C++程序设计语言(特别版)--源代码

    热门讨论 2012-04-23 07:33:51
    14.4.1 构造函数和析构函数的使用 325 14.4.2 auto_ptr 326 14.4.3 告诫 328 14.4.4 异常和new 328 14.4.5 资源耗尽 329 14.4.6 构造函数里的异常 331 14.4.7 析构函数里的异常 332 14.5 不是错误的异常 333 ...
  • 接口只可以定义static final成员变量。接口的实现与子类相似,除了该实现类不能从接口定义中继承行为。当类实现特殊接口时,它定义(即将程序体给予)所有这种接口的方法。然后,它可以在实现了该接口的类的任何对象...

空空如也

空空如也

1 2 3
收藏数 42
精华内容 16
关键字:

构造函数可以定义为虚函数吗