虚函数

qt5--鼠标操作

╄→尐↘猪︶ㄣ 提交于 2019-11-29 16:08:19
void enterEvent(QEvent *event); //鼠标进入事件 //此事件是个虚函数,需要自定义类重写 void leaveEvent(QEvent *event); //鼠标离开事件 //此事件是个虚函数,需要自定义类重写 来源: https://www.cnblogs.com/liming19680104/p/11521702.html

游戏开发面试总结2

风流意气都作罢 提交于 2019-11-29 15:04:29
总结一些面试常问的吧 1:聊一聊虚函数吧 C++中,虚函数主要是实现了多态机制,简而言之就是 用父类型的指针指向了子类型的实例,然后通过父类的指针去调用子类的成员函数。 每一个含有虚函数的类都至少有一个与之对应的虚函数表,存放着这个类所由虚函数对应的函数指针。 虚函数表在构建的过程中的步骤:    1:拷贝基类的虚函数表   2:替换重写的虚函数指针   3:追加子类的虚函数指针 这些步骤是编译器完成的 2: 虚析构函数:虚析构函数使得在删除指向子类对象的基类指针的时候可以调用子类的析构函数达到释放子类中堆内存的目的,防止内存泄漏 当delete父类的指针时,由于子类的析构函数和父类的析构函数形成多态,所以先调用子类的析构函数再调用父类的析构函数 。 纯虚函数:形式为virtual void fun() = 0; 不需要实现,因为不会被调用到 抽象基类:至少有一个纯虚函数的类,抽象基类不能产生改类的对象,但是可以有这个类的指针或者引用;子类中必须将纯虚函数实现,否则子类也是抽象基类 3: 聊一聊堆排序吧 堆排序分为两个步骤:   1:根据初始的输入数据,进行HeapAdjust形成初始堆     复杂度为O(n),包括比较和交换 公式可以写为s = 2^( i - 1 ) * ( k - i ),2^( i - 1) 表示该层上有多少个元素,( k - i)

C++多态原理与内部结构

陌路散爱 提交于 2019-11-29 14:59:05
多态类型 多态可以分为 静态多态 和 动态多态 : 静态多态其实就是重载 ,因为静态多态是指在编译时期在形成符号表的时候, 对函数名做了区分 ,根据参数列表来决定调用哪个函数, 也叫编译时多态 ; 动态多态是指通过子类重写父类的虚函数来实现 的,因为是 在运行期间决定调用的函数 ,所以称为 动态多态 ,一般情况下我们不区分这两个时所说的多态就是指动态多态。 动态多态的实现与虚函数表,虚函数指针相关,下面详述。 虚函数相关 首先我们来说一下,C++中多态的表象, 在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数 。如果对象类型是派生类,就调用派生类的函数,如果是基类,就调用基类的函数。 实际上, 当一个类中包含虚函数时,编译器会为该类生成一个虚函数表,保存该类中虚函数的地址 ,同样,派生类继承基类,派生类中自然一定有虚函数,所以 编译器也会为派生类生成自己的虚函数表 。当我们定义一个派生类对象时,编译器检测该类型有虚函数,所以为这个派生 类对象生成一个虚函数指针,指向该类型的虚函数表 ,这个虚函数 指针的初始化在构造函数中完成 的。后续如果有一个基类类型的指针,指向派生类,那么当调用虚函数时, 从对象的前4个字节中取虚表地址 ,根据所指真正对象的虚函数表指针去寻找虚函数的地址,也就可以调用派生类的虚函数表中的虚函数

C++三大特性(继承、封装、多态)

穿精又带淫゛_ 提交于 2019-11-29 12:25:59
封装 就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。一个类就是一个封装了数据以及操作这些数据的代码的逻辑实体。在一个对象内部,某些代码或某些数据可以是私有的,不能被外界访问。通过这种方式,对象对内部数据提供了不同级别的保护,以防止程序中无关的部分意外的改变或错误的使用了对象的私有部分。 继承 指可以让某个类型的对象获得另一个类型的对象的属性的方法。它支持按级分类的概念。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。 通过继承创建的新类称为“子类”或“派生类”,被继承的类称为“基类”、“父类”或“超类”。继承的过程,就是从一般到特殊的过程。要实现继承,可以通过 “继承”( Inheritance)和“组合”( Composition)来实现。继承概念的实现方式有三类:实现继承、接口继承和可视继承。 实现继承:是指直接使用基类的属性和方法而无需额外编码的能力; 接口继承:是指仅使用属性和方法的名称、但是子类必须提供实现的能力。 可视继承:可视继承是指子窗体(类)使用基窗体(类)的外观和实现代码的能力。 多态 是指一个类实例的相同方法在不同情形有不同表现形式。多态机制使具有不同内部结构的对象可以共享相同的外部接口。这意味着,虽然针对不同对象的具体操作不同

为什么构造函数不能是虚函数(转)

北城余情 提交于 2019-11-29 10:11:16
来源: http://blog.sina.com.cn/s/blog_620882f401016ri2.html 1,从存储空间角度 虚函数对应一个vtable,这大家都知道,可是这个vtable 的指针 其实是存储在对象的内存空间的。问题出来了,如果构造函数是虚的,就需要通过 vtable来调用,可是 对象还没有实例化,也就是内存空间还没有,无法找到vtable ,所以构造函数不能是虚函数。 2,从使用角度 虚函数主要用于在信息不全的情况下,能使重写的函数得到对应的调用。构造函数本身就是要初始化实例,那使用虚函数也没有实际意义呀。所以构造函数没有必要是虚函数。 虚函数的作用在于通过父类的指针或者引用来调用它的时候能够变成调用子类的那个成员函数。而 构造函数是在创建对象时自动调用的,不可能通过父类的指针或者引用去调用 ,因此也就规定构造函数不能是虚函数。 4、从实现上看,vbtl在构造函数调用后才建立,因而构造函数不可能成为虚函数 从实际含义上看,在调用构造函数时还不能确定对象的真实类型(因为子类会调父类的构造函数);而且构造函数的作用是提供初始化,在对象生命期只执行一次,不是对象的动态行为,也没有太大的必要成为虚函数 5、 当一个构造函数被调用时,它做的首要的事情之一是初始化它的V P T R 。因此,它 只能知道它是“当前”类的 ,而完全忽视这个对象后面是否还有继承者。

小结

南楼画角 提交于 2019-11-29 08:21:28
. 类成员函数的重载、覆盖和隐藏区别? 答:1.成员函数被重载的特征: (1)相同的范围(在同一个类中); (2)函数名字相同; (3)参数不同; (4)virtual 关键字可有可无。 2.覆盖是指派生类函数覆盖基类函数,特征是: (1)不同的范围(分别位于派生类与基类); (2)函数名字相同; (3)参数相同; (4)基类函数必须有virtual 关键字。 3.“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下: (1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。 (2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual 关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)。 重载(overload)和重写(overried,有的书也叫做“覆盖”)的区别? 答:从定义上来说: 重载:是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。 重写:是指子类重新定义父类虚函数的方法。 从实现原理上来说: 重载:编译器根据函数不同的参数表,对同名函数的名称做修饰,然后这些同名函数就成了不同的函数(至少对于编译器来说是这样的)。如,有两个同名函数:function func(p:integer):integer

C++实现多态的原理

感情迁移 提交于 2019-11-29 06:48:46
C++的多态是面向对象编程的核心,那么C++的多态是怎么来实现的?今天我们就来探讨一下。 我们先来看下面程序和它的运行结果 #include using namespace std; class Father { public: void fun() { cout << “I am father!” << endl; } }; class Son:public Father { public: void fun() { cout << “I am son!” << endl; } }; int main() { Son son; Father *Pfather= &son; Pfather->fun(); system(“pause”); return 0; } 我相信很多人可能会误将它和C++的多态搞混,认为Son的对象son应该调用Son的成员函数,但事实却不是如此,这是为什么呢? 答:从编译器的角度看: C++编译器在编译时,会确定每个对象调用函数(非虚函数)的地址,这叫做早期绑定(也叫做静态绑定)。 当我们定义了派生类的对象,并取它的地址赋值给基类的指针,这时编译器会自动为派生类对象进行类型转换,将派生类对象转换为基类对象,站在内存的角度来看,访问的就是基类的成员。这是因为派生类的对象的对象模型如下: 基类的成员属于派生类成员的一部分,那么父类和子类的成员变量如何初始化呢

构建之法读书笔记 第4章 两人合作

回眸只為那壹抹淺笑 提交于 2019-11-29 02:33:23
代码规范 一个人独立完成的软件已经很少见了(向独立游戏开发者致敬),软件都是在相互合作中完成的,最小单位: 俩人。 代码规范: 不同的人对代码好坏评判不同,需要基准 代码风格规范 文字上的规定,很重要 原则: 简明易读,无二义性 命名上应该一眼看出变量的类型和语义 匈牙利命名法: 给变量以有意义的前缀。对于强类型的语言不必要 Pascal: 所有单词首字母大写 Camel: 第一个单词小写,其余单词遵循Pascal 函数: 动词或者动宾来组合 注释 复杂的注释应该放在函数头 注释应该只用ASCII码 误导的注释比没有注释更糟糕 避免冗余的注释 代码设计规范 通用原则上的规范,牵涉模块关系等 函数 只做一件事,并且做好 goto 函数最好有单一的出口,为达此目的,可以使用goto ??以前都是听说要避免使用goto 错误处理 验证参数正确性 使用Assert 如何处理C++中的类 类的使用 使用类来封装面向对象的概念和多态 指针传递,避免传递实体的值 对于有显式构造和析构函数的类,避免建立全局的实体,因为不知道何时创建和消除 仅在必要时使用类 仅数据的封装,用struct即可 仅在必要时使用类型继承 关于数据成员和方法 按照public, protected, private 的顺序来说明类中的成员 使用虚函数来实现多态;仅在很有必要时使用虚函数;若一个类型要实现多态

操作系统

孤街醉人 提交于 2019-11-28 21:35:18
C的内存分配 32bitCPU可寻址4G线性空间, 每个进程都有各自独立的4G逻辑地址, 其中0~3G是用户态空间, 3~4G是内核空间, 不同进程相同的逻辑地址会映射到不同的物理地址中. 其逻辑地址其划分如下: 正文段(code segment/text segment, .text段): 或称代码段, 通常是用来存放程序执行代码的一块内存区域. 这部分区域的大小在程序运行前就已经确定, 并且内存区域通常属于只读, 某些架构也允许代码段为可写, 即允许修改程序. 在代码段中, 也有可能包含一些只读的常数变量, 例如字符串常量等 . CPU执行的机器指令部分. ( 存放函数体的二进制代码 . ) 只读数据段(RO data, .rodata):只读数据段是程序使用的一些不会被改变的数据, 使用这些数据的方式类似查表式的操作, 由于这些变量不需要修改, 因此只需放在只读存储器中. 已初始化读写数据段(data segment, .data段):通常是用来存放程序中已初始化的全局变量的一块内存区域. 数据段属于静态内存分配. 常量字符串就是放在这里的, 程序结束后由系统释放(rodata—read only data). 已初始化读写数据段(RW data, .data):已初始化数据是在程序中声明, 并且具有初值的变量, 这些变量需要占用存储器空间,

C++多态

喜夏-厌秋 提交于 2019-11-28 19:50:33
不规范的重写:在基类函数加了 virtual 关键字 ,在派生类中重写的成员函数前不加 virtual ,也是构成重写的。 接口结成和实现继承 普通函数的继承是一种实现继承,派生类继承了基类函数,可以使用函数,继承的是函数的实现。虚函数的 继承是一种接口继承,派生类继承的是基类虚函数的接口,目的是为了重写,达成多态,继承的是接口。所 以如果不实现多态,不要把函数定义为 [https://blog.csdn.net/weixin_42678507/article/details/89414998]: 虚函数。 多态的定义和实现:https://blog.csdn.net/weixin_42678507/article/details/89414998 多态的实现原理:https://blog.csdn.net/weixin_42678507/article/details/89467387 多态的四种表现形式:https://blog.csdn.net/weixin_42678507/article/details/97111466 来源: https://blog.csdn.net/qq1024734546/article/details/100120560