派生类地址比基类地址少4(CDerived对象的起始地址存放的是虚表指针vptr,也就是子类的第一项内容。接下来的是基类的成员变量,接下来再是自身的成员变量)
大家对虚表并不陌生,都知道每个含有虚函数的类对象都有1个虚指针,但是在现实使用中,却总是因为这而调试半天,才发现原来是虚指针惹的祸。我这几天在调试代码时候也中招了,我的问题是这样的,如下图,CTree是最底层基类(非虚类), CSamplerTree(虚类)派生自CTree,CMSamplerTree,CASamplerTree派生自CSamplerTree,
CTree中包括两个成员变量,QList <CTree *> childList;树中有多少个孩子节点;CTree *parent;当前树节点的父亲节点,程序中我大量使用CTree *pTree指针指向CSamplerTree、CMSamplerTree、CASamplerTree ,从而达到统一处理的目的,从而使代码很简洁,复用性高。但是谁曾想到,程序一运行就会崩溃,通过调试发现,CSamplerTree、CMSamplerTree、CASamplerTree的指针当指向CTree的指针时,地址均加了4,为什么呢?为了加深理解,我做了一个简单的测试代码:
- #include <stdio.h>class CBase {
- public:
- CBase() {}
- void func()
- {
- printf("base\n");
- }
- };
- class CDerived : public CBase {
- public:
- CDerived() {}
- virtual void func1()
- {
- printf("derived\n");
- }
- };
- void main()
- {
- CBase *pBase = new CDerived();
- pBase->func();
- CDerived *pDerived = (CDerived *)pBase;
- printf("%d %d\n", pDerived, pBase);
- pDerived->func();
- CBase *pBase1 = new CBase();
- pBase1->func();
- CDerived *pDerived1 = (CDerived *)pBase1;
- printf("%d %d\n", pDerived1, pBase1);
- pDerived1->func();
- }
下面是输出的结果,从结果可以看出派生类指针指向基类指针,指针地址会加4,基类指针指向派生类时,指针地址会减4。
base
200672 200676
derived
base
200740 200744
Press any key to continue
下面我们看看派生类对象和基类对象的内存是如何组织的,我们在上例的基础上引入2个变量,代码如下:
- #include <stdio.h>class CBase {
- public:
- CBase() {}
- void func()
- {
- printf("base\n");
- }
- int a;
- };
- class CDerived : public CBase {
- public:
- CDerived() {}
- virtual void func1()
- {
- printf("derived\n");
- }
- int b;
- };
- void main()
- {
- CBase *pBase = new CDerived();
- CDerived *pDerived = (CDerived *)pBase;
- printf("%d %d\n", pDerived, pBase);
- printf("%d %d %d\n", &pDerived->a, &pDerived->b, &pBase->a);
- }
200672 200676
200676 200680 200676
Press any key to continue
从输出结果我们可看出,CDerived对象的起始地址存放的是虚表指针vptr,接下来的是基类的成员变量,接下来再是自身的成员变量。
https://blog.csdn.net/rabinsong/article/details/8923137
派生类地址比基类地址少4(CDerived对象的起始地址存放的是虚表指针vptr,也就是子类的第一项内容。接下来的是基类的成员变量,接下来再是自身的成员变量)的更多相关文章
- c++派生类中构造函数和析构函数执行顺序、判断对象类型、抽象类、虚函数
一. 代码: 1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #include&l ...
- C++ 虚指针、成员变量与类对象的偏移地址
先给出一段代码实现 #include <iostream> using namespace std; class animal { protected: int age; public: ...
- 基类中定义的虚函数在派生类中重新定义时,其函数原型,包括返回类型、函数名、参数个数、参数类型及参数的先后顺序,都必须与基类中的原型完全相同 but------> 可以返回派生类对象的引用或指针
您查询的关键词是:c++primer习题15.25 以下是该网页在北京时间 2016年07月15日 02:57:08 的快照: 如果打开速度慢,可以尝试快速版:如果想更新或删除快照,可以投诉快照. ...
- Effective Objective-C 2.0 — 第二条:类的头文件中尽量少引入其他头文件
第二条:类的头文件中尽量少引入其他头文件 使用向前声明(forward declaring) @class EOCEmployer 1, 将引入头文件的实际尽量延后,只在确有需要时才引入,这样就可以减 ...
- C#多态;父类引用指向子类对象;new和override的区别;new、abstract、virtual、override,sealed关键字区别和使用代码示例;c#类的初始化顺序
关于父类引用指向子类对象 例如: 有以下2个类 public class Father { public int age = 70; public static string name = " ...
- java基础课程笔记 static 主函数 静态工具类 classpath java文档注释 静态代码块 对象初始化过程 设计模式 继承 子父类中的函数 继承中的构造函数 对象转型 多态 封装 抽象类 final 接口 包 jar包
Static那些事儿 Static关键字 被static修饰的变量成为静态变量(类变量) 作用:是一个修饰符,用于修饰成员(成员变量,成员方法) 1.被static修饰后的成员变量只有一份 2.当成员 ...
- Java之面向对象概述,类,构造方法,static,主方法,对象
一.面向对象概述 面向过程 "面向过程"(Procedure Oriented)是一种以过程为中心的编程思想.这些都是以什么正在发生为主要目标进行编程,不同于面向对象的是谁在受影响 ...
- Java学习笔记13---如何理解“子类重写父类方法时,返回值若为类类型,则必须与父类返回值类型相同或为其子类”
子类重新实现父类的方法称重写:重写时可以修改访问权限修饰符和返回值,方法名和参数类型及个数都不可以修改:仅当返回值为类类型时,重写的方法才可以修改返回值类型,且必须是父类方法返回值的子类:要么就不修改 ...
- C++类和对象(一)&&实现offsetof宏&&this指针
一.目录 1.对象的相关知识 2.类的定义 3.类的实例化 4.类对象模型 5.模拟实现offsetof宏 6.this指针 二.正文 1.对象的相关知识 C语言是面向过程的,关注的是过程,分析求解问 ...
随机推荐
- docker(三):Harbor 1.8.0 仓库的安装和使用
回顾: docker(一):docker是什么? docker(二):CentOS安装docker docker(部署常见应用):docker部署mysql 安装的先决条件 硬件环境 1.CPU ...
- TreeSet中的排序问题——Comparable
package com.etc.hashset; import java.util.HashSet; import java.util.Iterator; import java.util.Set; ...
- Fabric quickly
环境很重要.环境很重要.环境很重要 # CentOS 7 $ setenforce 0 # 可以设置配置文件永久关闭 $ systemctl stop iptables.service $ syste ...
- [Offer收割]编程练习赛35
有歧义的号码 #include<stdio.h> #include<string.h> #include<stdlib.h> int cmp(const void ...
- 豆瓣项目(用react+webpack)
用豆瓣电影api的项目 电影列表组件渲染 步骤: 1. 发送Ajax请求 1.1 在组件的componentWillMount这个生命周期钩子中发送请求 1.2 发送ajax XMLHttpReque ...
- WebStorm2018.2 破解 激活
1.进入http://idea.lanyus.com/,如图: 2.下载http://idea.lanyus.com/jar/JetbrainsCrack-3.1-release-enc.jar . ...
- 一款APP的开发设计是如何从0到1一步一步设计的
目前在行业里,关于APP界面设计规范也是层次不齐,很多都还停留在6的设备和ios 9的系统之上,而现在最新的是iphone 7和iOS 10了(更新换代真的很快),我这里说的是最新的iOS 界面设计规 ...
- PostgreSQL的HA解决方案-项目概述
公司使用的数据库时postgresql,一直运行都很流畅,但是最近java新做的管理平台,由于登录用户较多,并发性比较大.另外新系统可能优化也存在问题,所以pg经常崩溃,所以我就开始研究如何事项pg的 ...
- 我的C++笔记(类与对象)
/* * Main.cpp * * Created on: 2015-7-24 * Author: feiruo */ /* * 类与对象: * * 1.抽象: * 面向对象方法中的抽象,是指对具体问 ...
- CSS读书笔记(3)---清除浮动的几种方法
浮动元素容易造成页面错位现象.下面说说关于清除浮动的几种方法. 首先.先创建一个浮动导致错位的页面. <!DOCTYPE html> <html lang="en" ...