虚函数

C++对象模型学习

北城余情 提交于 2020-04-06 13:43:51
更新记录 时间 更新记录 2020年4月6日 初稿 背景 自从转入iOS,学习到iOS的方法调度,runTime的知识,了解了一下iOS的对象模型。 为了对iOS有更深入的了解,也对之前所学习的C++做一些补充,特此先学习一下C++的对象模型(说来也惭愧,windows开发一年半,没有看到C++对象模型相关的书或者网文) 三种对象模型 简单对象模型 所有的成员变量、成员函数都作为对象在内存中的一部分 简单、粗暴 缺点:占用内存大,以生成对象个数线性递增。 函数是所有对象共用,其实没有必要每个对象都记录,可以统一到某个地方。 表格驱动模型 区分数据成员和函数成员 对象只存放数据表指针和函数表指针,所以对象内存固定 针对于简单对象模型,表格驱动模型把数据成员列表作为每个对象独有的内存数据,而成员函数表则作为所有对象共享的内存数据,即可以解决简单对象模型“占用内存多”的问题 缺点 无法支持多态(确切地说,支持起来就比较复杂或者麻烦) 查找数据成员时,较第一种方案多了一次寻址。而且每个对象都多了一个表格指针,内存升高了。 (要知道C++可是非常重视性能的,每次查找数据成员都要多一次寻址,而数据成员可能用的很多) 调用成员函数时,较第一种方案多了一次寻址。 同上,C++的成员函数也可能调用的很频繁 当前的C++对象模型 对象第一个字节(32位系统下)存储虚函数表指针(如继承树上有虚函数)

抽象函数和虚函数有什么区别?

馋奶兔 提交于 2020-04-06 01:01:50
问题: What is the difference between an abstract function and a virtual function? 抽象函数和虚函数有什么区别? In which cases is it recommended to use virtual or abstract? 建议在哪种情况下使用虚拟或抽象? Which one is the best approach? 哪种方法最好? 解决方案: 参考一: https://stackoom.com/question/1dqF/抽象函数和虚函数有什么区别 参考二: https://oldbug.net/q/1dqF/What-is-the-difference-between-an-abstract-function-and-a-virtual-function 来源: oschina 链接: https://my.oschina.net/stackoom/blog/3217467

天书夜读:从汇编语言到Windows内核编程笔记(3)

时间秒杀一切 提交于 2020-04-05 22:03:24
Windows 内核(一) .sys 放在 Drivers 目录下。运行在 R0 层。 在 WDK 的相应环境中,进行相应代码目录, build. 一个内核程序被看作一个 PE 格式的 DLL ,它是被 Windows 整个内核调用的一个 DLL ,一旦加裁,就成为内核的组成部分。所有的内核内存空间是共享的。内核程序崩溃, Windows 系统也就崩溃了。 DriverEntry 是一个内核程序的入口,以 system 进程名出现。 编写内核的规则: 不能调用 Windows 应用层 API 函数,而应用内核 API 。 关于字符串,内存处理,打印等,参见前面 Rtl 函数 浮点数要特殊处理 在 Windows 中,不同类型设备的驱动有不同的安装方式, ini 文件。非 “ 任何类型 ” 的驱动程序,当作服务安装。(搜 “ 服务安装驱动下载 ” , net start 服务名) 调试 Windbg ( http://www.microsoft.com/whdc/devtools/debugging/installx86.mspx ) 我们用虚拟机进行调试 VMWare. 环境搭建: 1 、 虚拟机中 boot.ini ....... multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Windows Server 2003,

C++学习笔记45:多态性

安稳与你 提交于 2020-03-30 21:23:37
运算符重载 运算符是针对新类型数据的实际需要,对原有运算符进行适当的改造 1.比如使复数类的对象可以使用+运算符实现加法; 2.比如使时钟类的对象可以用++运算符实现时间增加1秒; 注意:可以重载为类的非静态成员函数、非成员函数 重载为类成员的运算符函数定义形式: 函数类型 operator 运算符(形参) {   ... } //参数个数=原操作数个数减1,(后置++,--除外) 如何重载运算符为非成员函数? 有些运算符不能重载为成员函数,例如二元运算符的左操作数不是对象,或者不能由我们重载运算符的对象; 备注:如果在重载运算符函数中要操作某类对象的私有成员,可以将此函数声明为该类的友元; 后置单目运算符的重载函数,形参列表中要增加一个int,但不必写形参名: 例如: 表达式 oprd B 等同于operator B(oprd,0) 虚函数: 通过虚函数实现运行时多态性,实现动态绑定; 虚函数必须是非静态的成员函数(属于对象的,而不是类的),虚函数经过派生后就可以实现运行过程中的多态; 注释: 一般的成员函数可以是虚函数; 构造函数不能是虚函数; 析构函数可以是虚函数; 虚函数一般不声明为内联函数,因为内联函数的处理是静态的; 虚析构函数 可能通过基类指针删除派生类的对象;如果需要通过基类指针调用对象的析构函数,就需要让基类的析构函数成为虚函数; 虚表与动态绑定 虚表

Java 对象布局及其组成

吃可爱长大的小学妹 提交于 2020-03-30 18:56:57
Java 对象布局及其组成 在 hotspot 虚拟机中,对象在内存中布局可以被分为三部分:对象头/实例数据/补位数据。下面一张图是一个普通 java 对象和一个数组对象的结构组成: Java 对象组成 Hotspt 采用了 OOP-Klass 模型。 它是描述 java 对象实例的模型,可分为两部分: OOP (Ordinary Object Pointer)指的是普通对象指针,它包含 MarkWord 和Klass 指针。MarkWord 用于存储当前对象运行时的一些状态数据;Klass 指针则指向 Klass,用来告诉当前指针指向的对象是什么类型,即对象是使用哪个类创建出来的 之所以采用这种一分为二的对象模型,是因为 hotspot jvm 的设计者不想让每个对象中都包含一个 virtual table (虚函数表), 所以把对象模型拆成 klass 和 oop,其中 oop 不包含任何虚函数,而 klass 含有虚函数表,可以进行method dispatch 对象的模型如下: volatile markOop _mark; //标识运行时数据 union _metadata { Klass* _klass; narrowKlass _compressed_klass; } _metadata; //klass指针 对象头 对象头主要有两部分(数组对象有三组分)组成。

c++学习笔记:多态

僤鯓⒐⒋嵵緔 提交于 2020-03-30 17:21:18
1.多态:通常是指对于同一个消息、同一种调用,在不同的场合,不同的情况下,执行不同的行为--->重载便是简单的多态 ------->指同一个操作作用于不同的对象就会产生不同的响应; 多态性分为静态多态性和动态多态性   其中函数重载和运算符重载属于静态多态性, 虚函数属于动态多态性---->C++是依靠虚函数来实现动态多态的。 2.C++编译器根据传递给函数的参数和函数名决定具体要使用哪一个函数,称为联编:   1)在编译过程中进行的联编叫静态联编(static binding)或早期联编(early binding)。   2)在程序运行时完成,动态联编”(dynamic binding)也叫晚期联编(late binding)---->C++通过虚函数来实现动态联编 3.虚函数:vitual   1.与基类的虚函数有相同的参数个数;   2.与基类的虚函数有相同的参数类型;   3.与基类的虚函数有相同的返回类型。   注意点:1. 基类的成员函数定义为虚函数,那么,它在所有派生类中也保持为虚函数;即使在派生类中省略了virtual关键字,也仍然是虚函数。       2.构造函数不可为虚函数--->一旦为虚函数相当于重新,在构造子类时无法找到基类构造函数从而无法构造对象。       ( 1. 根据继承的性质,构造函数执行顺序是: A() B() 2. 根据虚函数的性质

C++基础学习笔记

ぐ巨炮叔叔 提交于 2020-03-30 17:19:57
  虚函数:虚函数是动态绑定的基础。虚函数必须是非静态的成员函数,虚函数经过派生后在类族中就可以实现运行过程中的多态。   根据类型兼容原则,可以使用派生类的对象代替基类对象。如果用基类类型的指针指向派生类对象,就可以通过这个指针来访问该对象, 问题是访问到的只是从基类中继承来的同名函数。 解决办法:若需要通过基类指针指向派生类对象,并且访问某个与基类同名的成员,首先在基类中将该同名函数声明为 虚函数。 如此,通过基类类型的指针,就可使属于不同派生类的不同对象产生的不同的行为,从而实现运行过程的多态。    虚函数在类的定义中使用 virtual 关键字来限定成员函数。注:虚函数声明只能出现在类定义中的函数原型声明中,而不能在成员函数实现的时候。   运行时多态需满足三个条件:1、类之间满足 类型兼容原则 。2、要声明 虚函数 。3、 由成员函数来调用或通过指针、引用来访问虚函数 。 #include <iostream> using namespace std; class B0 { public: virtual void display(){cout << "B0::display()" <<endl;} }; class B1:public B0 { public: void display(){cout << "B1::display()" <<endl;} };

函数重载(overload)和函数重写(override)

為{幸葍}努か 提交于 2020-03-30 08:12:26
1. 前言:   在C++中有两个非常容易混淆的概念,分别是函数重载( overload )和函数重写( overwirte )。虽然只相差一个字,但是它们两者之间的差别还是非常巨大的。   而通过深入了解这两个概念的区别,会对C++的面向对象机制有一个更深入的理解。 2 函数重载(overload function) 2.1 函数重载的概念: 2.1.1 概念: 当函数具有相同的名称,但是 参数列表不相同 的情形( 包括参数的 个数不同 或参数的 类型不同 ),这样的 同名而不同参数 的函数之间,互相被称之为重载函数。 2.1.2 基本条件: 函数名必须相同; 函数参数必须不相同,可以是参数类型或者参数个数不同; 函数返回值可以相同,也可以不相同。(备注: 但是如果函数的名称和参数完全相同,仅仅是返回值类型不同,是无法进行函数重载的。 ) 2.1.3 注意: 只能通过不同的参数样式进行重载,例如:不同的参数 类型 ,不同的参数 个数 ,或者不同的参数 顺序 ; 不能通过访问权限、返回类型、抛出的异常不同而进行重载; 重载的函数应该在相同的作用域下。 2.1.4 函数重载实例判断: 以下的集中写法,分别表示了哪些是重载的,哪些不是重载的。 (1) void func1( int arg1); (2) void func1( double arg1); (3) void func1(

C++类内存分布

房东的猫 提交于 2020-03-30 02:39:27
转自:http://www.cnblogs.com/jerry19880126/p/3616999.html C++类内存分布 书上类继承相关章节到这里就结束了,这里不妨说下C++内存分布结构,我们来看看编译器是怎么处理类成员内存分布的,特别是在继承、虚函数存在的情况下。 工欲善其事,必先利其器,我们先用好Visual Studio工具,像下面这样一步一步来: 先选择左侧的C/C++->命令行,然后在其他选项这里写上/d1 reportAllClassLayout,它可以看到所有相关类的内存布局,如果写上/d1 reportSingleClassLayoutXXX(XXX为类名),则只会打出指定类XXX的内存布局。近期的VS版本都支持这样配置。 下面可以定义一个类,像下面这样: 1 class Base 2 { 3 int a; 4 int b; 5 public: 6 void CommonFunction(); 7 }; 然后编译一下,可以看到输出框里面有这样的排布: 这里不想花精力在内存对齐因素上,所以成员变量都设为int型。 从这里可以看到普通类的排布方式,成员变量依据声明的顺序进行排列(类内偏移为0开始),成员函数不占内存空间。 再看下继承,往后面添加如下代码: 1 class DerivedClass: public Base 2 { 3 int c; 4 public

C++四种强制转换

梦想的初衷 提交于 2020-03-30 02:37:35
C语言的强制转换为在数据面前之间加数据类型进行转换,即(目标数据类型)原数据类型。 c++ 为了更好的 区分强制转换的类型 ,达到 见其名知其意 的效果,共将强制转换分为四种,即 1、static_cast<目标数据类型>原数据类型 2、const_cast<目标数据类型>原数据类型 3、reinterpret_cast<目标数据类型>原数据类型 4、dynamic_cast<目标数据类型>原数据类型 解析 static_cast<>() 1)用于类层次结构中基类和派生类之间指针或引用的转换 进行上行转换(把派生类的指针或引用转换成基类表示)是安全的 进行下行转换(把基类的指针或引用转换为派生类表示),由于没有动态类型检查,所以是不安全的 2)用于基本数据类型之间的转换,如把int转换成char。这种转换的安全由开发人员来保证 3)把空指针转换成目标类型的空指针 4)把任何类型的表达式转换为void类型 注意:static_cast不能转换掉expression的const、volitale或者__unaligned属性。  static_cast:可以实现C++中内置基本数据类型之间的相互转换。 如果涉及到类的话,static_cast只能在 有相互联系的类型中进行相互转换, 不一定包含虚函数。 const_cast<>() cost_cast即用于强制转换 指针或者引用 的