指针变量

C++类继承内存布局(三)

落爺英雄遲暮 提交于 2020-01-22 21:36:18
参考:http://blog.csdn.net/jiangyi711/article/details/4890889# (三)成员函数 类X中每一个非静态成员函数都会接受一个特殊的隐藏参数——this指针,类型为X* const 该指针在后台初始化为指向成员函数工作于其上的对象 在成员函数内,成员变量的访问是通过在后台计算与this指针的偏移来进行 struct P { int p1; void pf(); // new virtual void pvf(); // new }; 声明虚成员函数会造成对象实例占用更多的内存空间,因为虚成员函数需要虚函数表指针 声明非虚成员函数不会造成对象实例的任何内存开销 P:pf()的点定义: void P::pf() { // void P::pf([P *const this]) ++p1; // ++(this->p1); } P:pf()接收了一个隐藏的this指针参数,对每个成员函数的调用,编译器都会自动加上这个参数 在pf()函数内,对于成员变量的访问全部通过this指针进行, 有的继承层次下this指针需要调整,访问成员的开销会增大 1)覆盖成员函数 和成员变量一样,成员函数也会被继承。通过在派生类中重新定义基类函数,一个派生类可以覆盖基类函数定义 覆盖是静态的还是动态的依赖于成员函数是否被声明为虚函数 class A {

C++的那些事:面向对象

人盡茶涼 提交于 2020-01-22 20:56:10
1 OOP概述 面向对象基于三个基本概念:数据抽象、继承和动态绑定。通过使用数据抽象,我们可以将类的接口与实现分离;使用继承,可以定义相似的类型并对其相似关系建模;使用动态绑定,可以在一定程度上忽略相似类型的区别,而以统一的方式使用它们的对象。 1.1 继承 继承是派生类与基类之间的关系,它们共享了一些公共的东西,而派生类特化了一些本质不同的东西。类与类之间的继承关系构成了继承层次。在C++中,基类必须指定希望派生类重定义哪些函数,定义为virtual的函数是基类期待派生类重新定义的,需要在派生类中继承的不能定义为虚函数。 派生类重新定义的虚函数前面可以加virtual,但这不是必要的,在C++11中,允许派生类显式地注明它将使用哪个成员函数改写基类虚函数,只用在该函数形式参数列表后增加一个override关键字。 1.2 动态绑定 当函数接口定义了基类的引用(或指针)时,在函数内调用虚函数时,发生动态绑定。因为这时候函数实参可以为基类类型也可以为派生类类型, 虚函数只有在运行阶段 才能确定需要调用哪个定义。 2 定义基类与派生类 2.1 定义基类 基类成员函数中希望在派生类中重新定义的函数前面加了virtual,这类函数在调用时,在程序运行阶段确定。任何构造函数之外的非静态函数都可以是虚函数。virtual关键字只需要在基类定义的时候加在需要重定义的函数前面,实现的时候不需要。

C++-Record25—C++面向对象模型初探

て烟熏妆下的殇ゞ 提交于 2020-01-22 19:27:37
目录 基本知识 汇总 this指针 总体代码 通过之前的学习,知道类里面有普通成员变量和静态成员变量,那么请问编译器是如何管理这些变量的?这个涉及到编译器如何在面向过程的基础之上提供面向对象的设计。这个话题异常重要,也决定了是否能从面向过程的思路上,转化到面向对象上来。 本次初探,目的是弄明白C++编译器是如何实现类型的封装的。 1. 语言中直接支持面向对象程序设计的部分,主要涉及如构造函数、析构函数、虚函数、继承(单继承、多继承、虚继承)、多态等等。 2. 对于各种支持的底层实现机制。 在c语言中, “数据”和“处理数据的操作(函数)”是分开来声明的 ,也就是说,语言本身并没有支持 “数据和函数” 之间的关联性。而在c++中,通过抽象数据类型(abstract data type,ADT),在 类中 定义数据和函数,来实现数据和函数直接的 绑定,也就是封装 。 概括来说,在C++类中有两种成员数据:static、nonstatic;三种成员函数:static、nonstatic、virtual。 基本知识 C++中的class从面向对象理论出发,将变量(属性)和函数(方法)集中定义在一起,用于描述现实世界中的类。从计算机的角度,程序依然由数据段和代码段构成。 C++ 编译器如何完成面向对象理论到计算机程序的转化? 换句话:C++编译器是如何管理类、对象、类和对象之间的关系的呢?

C++ const总结

不问归期 提交于 2020-01-22 05:52:38
编程中是否遇到这样情况? (基本内容来源于C++ Prime) 1、用一个变量表示缓冲区的大小。当我们觉得不合适时,直接改变变量值即可,可以很方便调整缓冲区大小 2、但要警惕程序不小心改变了这个值 OK,遇到这样情况,使用const修饰符即可。 言简意赅,总结一下。 首先上目录: 1、const对象必须初始化。 2、默认情况下,cosnt对象只在文件内有效 3、const的引用 4、const与指针 5、 顶层const 和 底层const 6、C++常量折叠 7、const函数 8、const成员变量 1、const对象必须初始化。 因为const对象一旦创建,就不能改变了。 2、默认情况下,cosnt对象只在文件内有效 下面论述一下const对象和普通对象的区别。 (转载于http://blog.csdn.net/yipiantiandi/article/details/5822564) (const对象默认作用域为:文件作用域) (普通变量默认作用域:整个程序) 对于一般的对象 如 int a=9;;我们知道它的作用域是整个程序的,在1.cpp和2.cpp中包含同一个定义了int a=9;的头文件,因为int a=9;作用域是整个程序,所以会产生错误。 那为什么 const int a=9;不会产生错误呢。 原因就是const int a=9;的默认作用范围是文件作用域的。即

C基础第29课--指针和数组分析(下)

帅比萌擦擦* 提交于 2020-01-22 04:58:56
学习自狄泰软件学院唐佐林老师C语言课程,文章中图片取自老师的PPT,仅用于个人笔记。 实验1 :数组的访问方式 #include <stdio.h> int main() { int a[5] = {0}; int* p = a; int i = 0; for(i=0; i<5; i++) { p[i] = i + 1; } for(i=0; i<5; i++) { printf("a[%d] = %d\n", i, *(a + i)); } printf("\n"); for(i=0; i<5; i++) { i[a] = i + 10; } for(i=0; i<5; i++) { printf("p[%d] = %d\n", i, p[i]); } return 0; } mhr@ubuntu:~/work/C$ gcc 29-1.c mhr@ubuntu:~/work/C$ mhr@ubuntu:~/work/C$ ./a.out a[0] = 1 a[1] = 2 a[2] = 3 a[3] = 4 a[4] = 5 p[0] = 10 p[1] = 11 p[2] = 12 p[3] = 13 p[4] = 14 mhr@ubuntu:~/work/C$ 实验2 :数组与指针的不同 ext.c int a[] = {1, 2, 3, 4, 5}; 29-2.c

C语言博客作业—字符数组

[亡魂溺海] 提交于 2020-01-22 02:55:06
一、PTA实验作业 题目1:字符串转换成十进制整数 1. 本题PTA提交列表 2. 设计思路 (1)定义i为循环变量,number用于存放每一次转化的结果,flag用于判断是否为负数,p用于修改结果的正负; (2)定义字符型数组hexad,并输入字符串; (3)for( from i=0 to hexad[i]!='#' ) //遍历数组 if(hexad[i]为'-'且flag为零0) //说明还没有遇到第一个十六进制字符 则结果为负数; if(hexad[i]在'0'到'9'之间) //挑出十六进制字符,转成相应的十进制 number=number*16+hexad[i]-48,flag=1; else if(hexad[i]在'A'到'F'之间) number=number*16+hexad[i]-55,flag=1; else if(hexad[i]在'a'到'f'之间); number=number*16+hexad[i]-87,flag=1; end (4)输出结果 3.代码截图。 4.本题调试过程碰到问题及PTA提交列表情况说明。 一开始的思路是不太理解符号的判断规则所以想用另一个字符数组存放筛选过的字符串,然后再进行转换;但是没有办法判断好符号,所以去看了一下别的代码是怎么判断这个地方的,然后就引用了一个p来直接决定结果的正负; 而且这样就不需要两个字符数组了

C语言--字符数组

蹲街弑〆低调 提交于 2020-01-22 02:45:15
一、PTA实验作业 题目1:7-1 字符串转换成十进制整数 1. 本题PTA提交列表 2. 设计思路 主要思路流程: 筛选出十六进制字符和负号: 遍历数组ch1并计算十进制整数number: 判断十进制整数number的符号并输出: 3.代码截图 4.本题调试过程碰到问题及PTA提交列表情况说明。 问题1:不知道怎么把字母字符转化成整数计算 解决办法:网上百度。例:n=B-‘A’+10; 问题2:答案部分正确,不知道如何处理负号,输出的数没有正负之分 解决办法:在设计一遍算法,理一遍思路。最后重新把思路整理为定义一个数组存放筛选出来的字符串,如果这个数组的第一个字符是负号,则这个数是负数。 题目2:找最长的字符串 1. 本题PTA提交列表 2. 设计思路 3.代码截图 4.本题调试过程碰到问题及PTA提交列表情况说明。 问题: 错因: 题目3:指定位置输出字符串 1. 本题PTA提交列表 2. 设计思路 3.代码截图 4.本题调试过程碰到问题及PTA提交列表情况说明。 一开始写的时候没有注意ch1和ch2也是要输出的。 二、截图本周题目集的PTA最后排名。(2分) PTA排名 三、同学代码结对互评(1分) 1.互评同学名称 2.我的代码、互评同学代码截图(此处截图核心代码就好,不一定截图全部代码,图上指明是谁的代码。) 3.我和同学代码不同在哪里?有哪些各自优势

指针变量后面的中括号数组表示什么意思?

こ雲淡風輕ζ 提交于 2020-01-22 01:25:28
在看etherCAT_slave_c28x_hal.c代码块的时候遇到如下写法: /******************************************************************************************/ 解析: 1、其中:对于表达式pEsc[((offset<<1))],C语言处理成运算符,pEsc[((offset<<1))] 等价于 *(pEsc+(offset<<1)), 因为:在C语言里,指针和数组关系密切。*pEsc, 一旦有指向地址后,就可以看成 一维数组pEsc[], 哪种形式便于阅读理解,就可以用哪种形式,所以pEsc[((offset<<1))] 等价于 *(pEsc+(offset<<1))。 2、在编译器看来数组名与指针是同一概念,比如这里的st其实就是*st,在编译器编译时,自动会把所有的[]处理为*()(声明除外)。比如st[5]编译时就变成了*(st+5),ps[i]就是*(ps+i)。 3、malloc叫动态内存分配,是在程序运行时分配的内存,内存区域为动态如;数组是在编译时分配,所以定义时需要给定明确的长度,分配的内存在静态区。至于你说的指针用下标取值,其实是因为数组用下标取值其实是先转化为指针的——a[i]先转化为*(a+i)。 4、至于(volatile uint16_t *

数据结构与算法之美-链表

风流意气都作罢 提交于 2020-01-22 01:09:58
什么是链表 和数组一样,链表也是一种线性表。 从内存结构来看,链表的内存结构是不连续的内存空间,是将一组零散的内存块串联起来,从而进行数据存储的数据结构。 链表中的每一个内存块被称为节点Node。节点除了存储数据外,还需记录链上下一个节点的地址,即后继指针next。 链表的特点 插入、删除数据效率高,时间复杂度为O(1),只需更改指针指向即可。 随机访问效率低,时间复杂度为O(n),需要从链头至链尾进行遍历。 和数组相比,链表的内存空间消耗更大,因为每个存储数据的节点都需要额外的空间存储后继指针。 常见的链表结构 单链表 每个节点只包含一个指针,即后继指针。 单链表有两个特殊的节点,即首节点和尾节点。 用首节点地址表示整条链表,尾节点的后继指针指向空地址null。 性能特点,插入和删除节点的时间复杂度为O(1),查找的时间复杂度为O(n)。 循环链表 除了尾节点的后继指针指向首节点的地址外均与单链表一致。 适用于存储有循环特点的数据,比如约瑟夫问题。 双向链表 节点除了存储数据外,还有两个指针分别指向前一个节点地址(前驱指针prev)和下一个节点地址(后继指针next)。 首节点的前驱指针prev和尾节点的后继指针next均指向空地址。 性能特点,和单链表相比,存储相同的数据,需要消耗更多的存储空间。 插入、删除操作比单链表效率更高,时间复杂度为O(1)。以删除操作为例

对Objective-C中Block的追探

匆匆过客 提交于 2020-01-21 22:27:00
最近看了很多block相关的文章,都在说block怎么用,写的都很精彩。 blogs: Block编程值得注意的那些事儿 (使用相关) http://www.cocoachina.com/macdev/cocoa/2013/0527/6285.html iOS中block实现的探究(内部结构分析) http://blog.csdn.net/jasonblog/article/details/7756763?reload 还有绪斌同学共享的(内部结构分析) https://www.evernote.com/shard/s269/sh/23b61393-c6dd-4fa2-b7ae-306e9e7c9639/131de66a3257122ba903b0799d36c04c?noteKey=131de66a3257122ba903b0799d36c04c&noteGuid=23b61393-c6dd-4fa2-b7ae-306e9e7c9639 又看了一本关于这方面的书: Pro Multithreading and Memory Management for iOS and OS X http://vdisk.weibo.com/s/9hjAV 觉得是可以总结一下我对block理解的时候了。 注:上面提供的资料有很多有用的背景知识比如block怎么用,什么时候应该加上_