虚函数

c++ 反汇编 虚函数

自作多情 提交于 2020-01-13 20:53:29
  虚函数是面向对象程序设计的关键组成部分。对于具有虚函数的类而言,构造函数和析构函数的识别流程更加简单。而且,在类中定义了虚函数之后,如果没有提供默认的构造函数,编译器必须提供默认的构造函数。   对象的多态性需要通过虚表和虚表指针来完成,虚表指针被定义在对象首地址的前4字节处,因此虚函数必须作为成员函数使用。由于非成员函数没有this指针,因此无法获得虚表指针,进而无法获取虚表,也就无法访问虚函数。 class CVirtual { public: ~CVirtual() { printf("~CVirtual"); } CVirtual() { } CVirtual(int nNumber) { m_nNumber = nNumber; } virtual int GetNumber() { return m_nNumber; } virtual void SetNumber(int nNumber) { m_nNumber = nNumber; } private: int m_nNumber; }; 类中只定义一个int类型的数据成员,类大小却为8。当类中含有虚函数时,对象空间中第一项存放虚表指针。 35: // 获取含有虚函数表的类大小 36: int nSize = sizeof(CVirtual); 0007739D C7 45 EC 08 00 00 00 mov

C++多态

吃可爱长大的小学妹 提交于 2020-01-13 02:59:38
静态多态:函数重载和运算符重载 静态多态也叫函数地址早绑定,在编译阶段确定函数地址。 动态多态 动态多态满足条件: 有继承关系 子类重写父类的虚函数 多态的使用: 父 类 的 指 针 或 引 用 指 向 ( 接 收 ) 子 类 对 象 \color{red} 父类的指针或引用指向(接收)子类对象 父 类 的 指 针 或 引 用 指 向 ( 接 收 ) 子 类 对 象 空类大小是1个字节 加上virtual后变成4字节,本质是一个 虚 函 数 ( 表 ) 指 针 \color{red} 虚函数(表)指针 虚 函 数 ( 表 ) 指 针 vfptr指向虚函数表,表内记录虚函数的地址。子类继承虚函数指针以后,在自己的空间也复制了一份虚函数表,如果重写了虚函数,则在虚函数表中替换掉父类中的虚函数地址。 # include <iostream> using namespace std ; class Animal { public : virtual void speak ( ) { cout << "动物在说话" << endl ; } } ; class Cat : public Animal { public : void speak ( ) { cout << "猫在说话" << endl ; } } ; void dospeak ( Animal & animal ) {

C++编译期多态与运行期多态

一曲冷凌霜 提交于 2020-01-12 21:18:02
前言 今日的C++不再 是个单纯的“带类的C”语言,它已经发展成为一个多种次语言所组成的语言集合,其中泛型编程与基于它的STL是C++发展中最为出彩的那部分。在面向对象C++编程中,多态是OO三大特性之一,这种多态称为运行期多态,也称为动态多态;在泛请添加链接描述 型编程中,多态基于template(模板)的具现化与函数的重载解析,这种多态在编译期进行,因此称为编译期多态或静态多态。在本文中,我们将了解: 什么是运行期多态 什么是编译期多态 它们的优缺点在哪 运行期多态 运行期多态 的设计思想要归结到类继承体系的设计上去。对于有相关功能的对象集合,我们总希望能够抽象出它们共有的功能集合,在基类中将这些功能声明为虚接口(虚函数),然后由请添加链接描述 子类继承基类去重写这些虚接口,以实现子类特有的具体功能。典型地我们会举下面这个例子: class Animal { public : virtual void shout() = 0; }; class Dog :public Animal { public: virtual void shout(){ cout << "汪汪!"<<endl; } }; class Cat :public Animal { public: virtual void shout(){ cout << "喵喵~"<<endl; } }; class

C++虚函数内存对象模型

余生长醉 提交于 2020-01-11 02:02:46
文章目录 C++虚函数内存对象模型 1. 简单继承 2. 简单继承后子类新增虚函数 3. 继承的虚函数并非最初子类 4. 多继承 5. 总结 C++虚函数内存对象模型 面向对象的精彩都是通过多态引起的,通过多态,我们可以完成抽象和封装,并且做到针对抽象编程,给项目的扩展带来了很多的便利。 在C++中多态的实现有两种方式: 重载。 继承。 重载其实并不能算作完美的面向对象的多态,继承才是。我们知道继承的多态主要依赖虚函数来实现,那么C++底层是如何实现虚函数的呢?本文来深度探索一下C++基于虚函数的多态对象模型。 1. 简单继承 在这个场景我们来看一下一个最简单的继承关系: 代码实现如下 class CLevel1 { public : CLevel1 ( ) { } virtual ~ CLevel1 ( ) { } virtual void Fun1 ( ) { std :: cout << "CLevel1 Fun1" << std :: endl ; } private : int m_Data1 = 100 ; } ; class CLevel2 : public CLevel1 { public : CLevel2 ( ) { } virtual ~ CLevel2 ( ) { } virtual void Fun1 ( ) override { std :: cout

NSFX手册的学习(1)

拥有回忆 提交于 2020-01-10 12:22:43
(边学手册边学C++) 组件的行为由组件所提供和使用的接口决定。组件通过一系列 的接口 来实现其函数功能的。目标模型的根接口是IObject。每一个接口一定直接或间接地从IObject衍生出来。每一个组件都一定会应用到IObject。 我们来看下面这个例子: class IObject { public: virtual ~IObject(void) BOOST_NOEXCEPT {} virtual refcount_t AddRef(void) = 0; virtual refcount_t Release(void) = 0; virtual void* QueryInterface(const Uid& iid) = 0; };IObject这个类定义了四个虚函数。---------------我们来看一下关于虚函数的知识:*虚函数是为了实现多态性的。*基类指针只能访问派生类的成员变量,但是不能访问派生类的成员函数。为了让基类指针能够访问派生类的成员函数,c++增加了虚函数。使用虚函数非常简单,只需要在函数声明前面增加virtual关键字。*有了虚函数,基类指针指向基类对象时就使用基类的成员(包括成员函数和成员变量),指向派生类对象时就使用派生类的成员。*换句话说,基类指针可以按照基类的方式来做事,也可以按照派生类的方式来做事,它有多种形态,或者说有多种表现方式

C++中的显示类型转换

拥有回忆 提交于 2020-01-10 08:49:01
C++中显示转换也成为强制类型转换(cast),有四种:static_cast、dynamic_cast、const_cast、reinterpret_cast。命名的强制类型转换符号一般形式如下: cast_name<type>(expression); 以下分别介绍 一、static_cast 任何具有明确定义的类型转换,只要不包含底层const都可以使用static_cast。好吧这句话我不是很懂,换句话:编译器隐式执行的任何类型转换都可以由static_cast显示完成。也就是说,两类型之间可以发生隐式的转换,就可以用static_cast显示转换,有点意思。但要知道的是C++基本类型的指针之间不含有隐式转换(void*除外、const的有些也是可以的),需要 显示转换 。什么意思?如下: double d=3.14; int i=d; //编译器的隐式转换,等价于下面这条语句 int i=static_cast<int>(d); /*指针之间的转换*/ char str[]="good"; char *ptr=str; int *p=static_cast<int *>(ptr); //编译错误,两者之间的转换要显式,如下 int *p=(int *)(ptr); 仅当类型之间可隐式转换时(除类层次见的下行转换以外),static_cast的转换才是合法的,否则将出错。

[转帖]二进制兼容

ぐ巨炮叔叔 提交于 2020-01-10 04:36:10
二进制兼容 https://www.jianshu.com/p/87febb375969 0.122016.07.28 16:32:57字数 721阅读 2,539 1. 什么是二进制兼容 所谓“二进制兼容性”指的就是在升级(也可能是 bug fix)库文件的时候,不必重新编译使用这个库的可执行文件或使用这个库的其他库文件,程序的功能不被破坏 2. 二进制不兼容会造成什么后果 如果库A升级没有能够做到二进制兼容,那么所有依赖它的程序(或库)都需要重新编译,否则会出现各种未知异常,其直接现象就是程序莫名其妙地挂掉。 3. 哪些常见做法会破坏二进制兼容 (1) 给函数增加默认参数,现有的可执行文件无法传这个额外的参数 (2) 增加虚函数,会造成 vtbl 里的排列变化。(不要考虑“只在末尾增加”这种取巧行为,因为你的 class 可能已被继承。) (3) 增加默认模板类型参数 例如:template<typename T> class Grid{}变更为template<typename t, typenameContianer=vector> class Grid{} (4) 改变 enum 的值,把 enum Color { Red = 3 }; 改为 Red = 4。这会造成错位。当然,由于 enum 自动排列取值,添加 enum 项也是不安全的,除非是在末尾添加 (5)

虚函数的若干细节

旧城冷巷雨未停 提交于 2020-01-06 22:43:59
一、在基类的某函数中调用虚函数的情况: 依然是动态绑定的,依然取决于基类指针实际指向的对象类型! 如: 派生类重写了虚函数print(); 仅在基类的test()函数调用print() 实际输出:Child 说明即使是在基类的某函数中调用虚函数,仍然要看对象的实际类型,是动态绑定的! 二、虚函数带默认实参的情况: 当虚函数有默认实参的时候,这个实参的默认值将在编译时确定,当调用虚函数的时候如果此参数没传入,那么默认值将使用“调用该虚函数的对象类型(并不是实际类型)来确定”!即不随动态绑定!与对象实际类型无关! 比如: (1)如果基类类指针调用了这个虚函数并不传参,那么参数的默认值是派生类里声明的值,而不管此基类指针实际指向了基类还是派生类! (2)如果派生类指针调用了这个虚函数并不传参,那么参数默认值是派生类里声明的值。 一个程序: 基类的虚函数:print(),默认实参值=0 派生类重写了虚函数print(),默认实参值=100 输出为:Child:0 而不是100! 默认实参的默认值是编译时确定的,由于b是Base类型指针,所以这里的i默认值 = Base类中print的i默认值,也就是0 所以,尽量让派生类虚函数的默认实参与基类的一致~ 来源: https://www.cnblogs.com/cppdaixiecs/p/12149340.html

C++ 基础知识复习(二)

▼魔方 西西 提交于 2020-01-05 04:24:21
异常处理部分: 23. 在c++的异常处理中,除了提供异常的关键字语法支持以外,其标准库中支持异常处理而封装异常类也很好的为应用程序中异常处理判断使用提供直接的帮助。C++语言中针对异常处理提供了三个关键字,分别为try、throw与catch。C++应用程序中通过这三个关键字实现机制组合来实现异常的处理。try体中可以直接抛出异常,或者在try体中调用的函数体中间接的抛出。注意catch是接thorw出来的数据的,数据类型上要兼容。 预处理及内存管理部分: 24. C语言提供的预处理功能有哪些: 答:宏定义,文件包含和条件编译。 25. include的使用方式: 答:include 如果包含的文件名在尖括号内,则为标准头文件,会在预定义的位置集进行查找。位置集可有环境变量或命令行修改。引号中为自定义头文件,查找始于源文件所在路径,一层层找直到系统文件目录。 26. 如何申请以及释放空间: 答:int *p; p=new int; *p=100; delete p; 注意如果要对这一内存地址进行操作,需要使用*号。 27. 什么是虚函数和纯虚函数: 答:虚函数用来建立抽象模型,从而达到方便系统扩展的目的,纯虚函数是指标明不具体实现的虚函数,是一种特别的虚函数。虚函数必须是基类定义的非静态函数,可以是protected活着public的。在一个类中,虚函数后面加上=0

C/C++ 复习

末鹿安然 提交于 2020-01-05 04:23:10
本文总结一下C++面试时常遇到的问题。C++面试中,主要涉及的考点有 关键字极其用法,常考的关键字有const, sizeof, typedef, inline, static, extern, new, delete等等 语法问题 类型转换 指针以及指针和引用的区别 面向对象的相关问题,如虚函数机制等 泛型编程的相关问题,如模板和函数的区别等 内存管理,如字节对齐(内存对齐)、动态内存管理、内存泄漏等 编译和链接 实现函数和类 本文不涉及STL的内容,有关STL的内容,会另有一篇文章专门总结。 零、序章 0.1 C++与C的对比 C++有三种编程方式:过程性,面向对象,泛型编程。 C++函数符号由 函数名+参数类型 组成,C只有函数名。所以,C没有函数重载的概念。 C++ 在 C的基础上增加了封装、继承、多态的概念 C++增加了泛型编程 C++增加了异常处理,C没有异常处理 C++增加了bool型 C++允许无名的函数形参(如果这个形参没有被用到的话) C允许main函数调用自己 C++支持默认参数,C不支持 C语言中,局部变量必须在函数开头定义,不允许类似for(int a = 0; ;;)这种定义方法。 C++增加了引用 C允许变长数组,C++不允许 C中函数原型可选,C++中在调用之前必须声明函数原型 C++增加了STL标准模板库来支持数据结构和算法 一