对象的内部表示

Internal representation of objects

本文关键字:表示 内部 对象      更新时间:2023-10-16

所以我一直认为当你做像ObjectA这样的东西时。field1, ObjectA就像堆栈上的任何值,你基本上访问它的字段。现在我正在浏览一门关于OOP语言的课程的笔记,并且意识到当你做ObjectA时。实际发生的是HEAP(ObjectA的地址)(field1),它返回field1的值。这让我有点困惑。有谁能告诉我为什么我们已经知道了对象的值还在查找吗?希望我能解释清楚…

对象并没有那么神奇。从本质上讲,对象只是由其所有成员的线性集合组成,成员周围的填充量未指定。在布局方面,c++类本质上类似于C结构体:

struct Foo {
  int a;
  char b;
  std::string s;
  static long q;
  void bar() { print(s); log(a); }
  static void car() { }
}

暂时忽略成员函数和静态函数,可以这样布局:

+= class Foo =+
+-------------+  ---   <---   Foo * p
|  int        |     s
+-------------+     i
|  char       |     z
+-------------+     e
| <padding>   |     o
+-------------+     f
| std::string |    (F
+-------------+     o
| <padding>   |     o)
+-------------+  ---/

Foo的每个对象都这样存储在内存中。惟一需要的额外数据是静态成员、成员函数和静态成员函数。

静态成员只是全局变量。所以我们只有一个全局变量:

+== static__Foo__q ==+
+--------------------+
|  long int          |
+--------------------+

接下来,静态成员函数就是普通的自由函数:

void static__Foo__car() {  }

最后,成员函数:这些本质上也是普通的函数,尽管有一个额外的参数允许它们查找实例成员:

void member__Foo__bar(Foo * p) { print(p->s); log(p->a); }

唯一重要的区别是,不能获得普通的指向成员函数的自由函数指针,因为没有公开实现函数的实际名称。引用Foo::bar()的唯一方法是通过指向成员函数void (Foo::*ptfm)() = &Foo::bar的指针。成员对象更简单一些:你可以获得一个普通的指针,比如Foo x; int * p = &x.a;,但是你也可以形成一个指向成员的指针:int Foo::*ptm = &Foo::a;

然后,如果有对象Foo x, y, z;,则可以使用实例指针Foo * pi = &x;和成员指针int &Foo::* ptm = &Foo::avoid (Foo::*ptfm)() = &Foo::bar访问给定实例的相关成员:整数pi->*ptm和函数调用(pi->*ptfm)()。(是的,->*是一个操作符。)

(不能存在自由版本的函数指针,因为多态(虚)函数需要比简单的固定函数指针更复杂的分派机制)

要获得某些ClassAObjectAfield1,计算机必须有包含ObjectA的内存区域的地址,它(静态地)知道field1 (ClassA)的偏移量(以字节为单位),因此它可以通过将该偏移量添加到ObjectA的地址来检索field1