成员在类中的偏移量 类成员指针

2024-06-06 22:08
文章标签 指针 成员 偏移量

本文主要是介绍成员在类中的偏移量 类成员指针,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章作者: Yx.Ac   文章来源: 勇幸|Thinking ( http://www.ahathinking.com)   转载请注明,谢谢合作。

---

看一道笔试题(引自程序员面试宝典):写出程序输出结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <stdio.h>
class A
{
public:
     A() {m_a = 1; m_b = 2;}
     ~A() {}
     void fun() {printf("%d %d", m_a, m_b);}
private:
     int m_a;
     int m_b;
};
class B
{
public:
     B() {m_c = 3;}
     ~B() {}
     void fun() {printf("%d", m_c);}
private:
     int m_c;
};
void main()
{
     A a;
     B *pb = (B*)(&a);
     pb->fun();
}

程序的输出结果为1。

暂且不讨论该程序设计有多么糟糕,但程序主要考察关于类对象成员调用的机制,关于这方面,据说在《深入理解C++对象模型》中有详解,我没有做深入研究,只是根据看《primer》和《C++必知必会》中的一些知识说一下自己的理解。

这里主要涉及到两方面:一是对象调用成员函数时会将调用对象与函数绑定;二是对象访问成员是根据该成员距离对象的偏移量来访问的,而不是根据成员名来访问,所谓偏移量,就是告诉你一个特定的成员位置距离对象的起点有多少个字节。

上面程序,内存中实例化了一个A类对象,然后将该地址强制转换成一个B类地址,即将该对象的地址内容强制看成一个B类对象。pb为B类的指针,理所当然调用的是B类中的fun()函数(可以跟多态的情形相比较),当调用fun()函数时,调用对象与该函数进行绑定,即fun()函数中隐含的形参this指针初始化为调用对象(A类对象)的地址,假设为0xff80。然后fun()函数打印值m_c。这里要注意,对象在访问类成员时,编译器并没有存储该对象各个成员的实际地址,而是存储了其相对于当前对象首地址的偏移量,由于B类只有一个成员m_c,在编译阶段,编译器就记录了m_c对于B类对象的偏移量为0,故访问m_c时,便是访问当前对象地址this+偏移量0,注意,this在这里绑定的是A类对象的首地址,在A类中,偏移量为0的成员是m_a,故打印出m_a的值。

关于类成员偏移量的输出,可以用程序验证。

例如如下程序:将地址0强制转换为A类对象的地址,那么打印类成员m_a和m_b的地址便是他们的偏移量,如下分别输出0, 4。

1
2
cout<<&((A*)0)->m_a<<endl;
cout<<&((A*)0)->m_b<<endl;

再如,我们可以通过输出类成员指针来验证。

1
2
printf("%p\n",&A::m_a);
printf("%p\n",&A::m_b);

分别输出 00000000,00000004。

如程序,&A::m_a实际是一个指向int型的A类的成员指针,用m_a初始化,即相当于:

1
int A::*ptr = &A::m_a;

这里说一下,输出成员指针的值,最好使用printf,%p输出指针,我曾试图使用语句

1
cout<<&A::m_a<<&A::m_b;

结果全是1。

究其原因,应该是ostream对象没有重载类成员指针的参数,故不能直接输出类成员指针的类型,而我们知道指针类型与bool类型的转换属于标准转换的(常常用来测试指针合法性是否为空),而ostream对象可以输出bool类型,故编译器将成员指针类型转换成了bool类型,从而输出,既然这样为什么全是输出1呢?说明地址全是合法的,即偏移量全是大于0,不对呀,第一个类成员的偏移量不是0么,这里真心不明白,不过《C++必知必会》中有这样一句话:大多数编译器都将成员指针实现为一个整数,包含被指向成员的偏移量,另外加上1(加1是为了让值0可以表示一个空的数据成员指针)。这大概就是全输出1的原因了吧。

关于成员指针

成员指针只是记录一个成员的偏移量,而非地址,因为类中没有地址,选择一个类的成员只是意味着在类中偏移,只有把这个偏移和具体对象的首地址结合,才能得到实际地址。

成员指针并不指向一个具体的内存位置,它指向的是一个类的特定成员,而不是指向一个特定对象的特定成员,最直接的理解是将其理解为一个偏移量。这个偏移量适用于某一类A的任何对象,换言之,如果一个A类对象的成员a距离起点的偏移量是4,那么任何其他A类对象中,a的偏移都是4字节。

啰嗦一大堆,总结一下就是两句话:

  1. 类对象访问其成员时,是根据该成员在类中的偏移量来访问的。
  2. 类成员指针,可以理解为指向类数据成员的一个偏移量,而非地址。

(全文完)

这篇关于成员在类中的偏移量 类成员指针的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1037362

相关文章

Java空指针异常NullPointerException的原因与解决方案

《Java空指针异常NullPointerException的原因与解决方案》在Java开发中,NullPointerException(空指针异常)是最常见的运行时异常之一,通常发生在程序尝试访问或... 目录一、空指针异常产生的原因1. 变量未初始化2. 对象引用被显式置为null3. 方法返回null

C++/类与对象/默认成员函数@构造函数的用法

《C++/类与对象/默认成员函数@构造函数的用法》:本文主要介绍C++/类与对象/默认成员函数@构造函数的用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录名词概念默认成员函数构造函数概念函数特征显示构造函数隐式构造函数总结名词概念默认构造函数:不用传参就可以

C++类和对象之默认成员函数的使用解读

《C++类和对象之默认成员函数的使用解读》:本文主要介绍C++类和对象之默认成员函数的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、默认成员函数有哪些二、各默认成员函数详解默认构造函数析构函数拷贝构造函数拷贝赋值运算符三、默认成员函数的注意事项总结一

查看MySql主从同步的偏移量方式

《查看MySql主从同步的偏移量方式》:本文主要介绍查看MySql主从同步的偏移量方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 1.mysql的主从同步方案mysqlphp为了在实现读写分离,主库写,从库读mysql的同步方案主要是通过从库读取主库的binl

go 指针接收者和值接收者的区别小结

《go指针接收者和值接收者的区别小结》在Go语言中,值接收者和指针接收者是方法定义中的两种接收者类型,本文主要介绍了go指针接收者和值接收者的区别小结,文中通过示例代码介绍的非常详细,需要的朋友们下... 目录go 指针接收者和值接收者的区别易错点辨析go 指针接收者和值接收者的区别指针接收者和值接收者的

Java Optional避免空指针异常的实现

《JavaOptional避免空指针异常的实现》空指针异常一直是困扰开发者的常见问题之一,本文主要介绍了JavaOptional避免空指针异常的实现,帮助开发者编写更健壮、可读性更高的代码,减少因... 目录一、Optional 概述二、Optional 的创建三、Optional 的常用方法四、Optio

解决java.lang.NullPointerException问题(空指针异常)

《解决java.lang.NullPointerException问题(空指针异常)》本文详细介绍了Java中的NullPointerException异常及其常见原因,包括对象引用为null、数组元... 目录Java.lang.NullPointerException(空指针异常)NullPointer

c++的初始化列表与const成员

初始化列表与const成员 const成员 使用const修饰的类、结构、联合的成员变量,在类对象创建完成前一定要初始化。 不能在构造函数中初始化const成员,因为执行构造函数时,类对象已经创建完成,只有类对象创建完成才能调用成员函数,构造函数虽然特殊但也是成员函数。 在定义const成员时进行初始化,该语法只有在C11语法标准下才支持。 初始化列表 在构造函数小括号后面,主要用于给

【C++学习笔记 20】C++中的智能指针

智能指针的功能 在上一篇笔记提到了在栈和堆上创建变量的区别,使用new关键字创建变量时,需要搭配delete关键字销毁变量。而智能指针的作用就是调用new分配内存时,不必自己去调用delete,甚至不用调用new。 智能指针实际上就是对原始指针的包装。 unique_ptr 最简单的智能指针,是一种作用域指针,意思是当指针超出该作用域时,会自动调用delete。它名为unique的原因是这个

C语言指针入门 《C语言非常道》

C语言指针入门 《C语言非常道》 作为一个程序员,我接触 C 语言有十年了。有的朋友让我推荐 C 语言的参考书,我不敢乱推荐,尤其是国内作者写的书,往往七拼八凑,漏洞百出。 但是,李忠老师的《C语言非常道》值得一读。对了,李老师有个官网,网址是: 李忠老师官网 最棒的是,有配套的教学视频,可以试看。 试看点这里 接下来言归正传,讲解指针。以下内容很多都参考了李忠老师的《C语言非