【问题标题】:In-class struct, how does "this" work?课堂结构,“这个”是如何工作的?
【发布时间】:2017-03-10 08:13:00
【问题描述】:

如前所述,this 指针在类中定义的结构中调用时如何作用? 假设我有以下代码:

class A {
public:
    struct {
        void bar() {  std::cout << this << std::endl;  }
    } foo;
};

int main() {
    A a; a.foo.bar();
    std::cout << &a << std::endl;
    std::cout << &a.foo << std::endl;
}

生成这个输出:

0x62fe9f
0x62fe9f
0x62fe9f

a.fooa 共享同一个地址,如何访问foothis 指针?

使用this-&gt;foo 会引发错误:

test.cpp:20:23: error: 'struct A::&lt;anonymous&gt;' has no member named 'foo'

【问题讨论】:

  • 在哪里你使用this-&gt;foo?您能否为 failing 程序创建一个Minimal, Complete, and Verifiable Example
  • a & foo 确实会共享同一个地址 - 因为 foo 是 A 的第一个成员。这就是为什么知道对象的类型很重要。
  • 我不明白这个问题。首先,在我看来struct S 完全无关紧要,您的问题只是关于AA::foo。其次,A::foo::bar()确实访问“(A::)foothis指针”。那么问题出在哪里?
  • 这里有一个提示:在A 中插入一个int 变量(紧跟在public 关键字之后),看看输出如何变化
  • 我错误地理解了我的问题,实际上foo 中的this 将指向foo,因此与a 具有相同的地址,是他的第一个成员!那么如何访问foo 中的a 指针呢?

标签: c++ class pointers struct this


【解决方案1】:

如果对象“开始”,地址主要是内存的位置。然后由类定义定义需要抵消多少成员。

所以课程A“开始”于0x62fe9f

类的开头A是成员foo所以因为它前面没有任何东西它也有地址0x62fe9f等。

当你把班级改成

class A {
public:
    int i;
    struct {
        void bar() {  std::cout << this << std::endl;  }
    } foo;
};

您应该看到&amp;a.i&amp;a 具有相同的地址,而&amp;a.foo 应该是&amp;a + sizeof(int)

(注意:它可能不止sizeof(int),在其他情况下也不同,因为如何设置填充。这只是一个简单的例子。你不应该依赖这个真实代码)

【讨论】:

  • 这并不是要在实际代码中使用,只是想知道它是如何工作的!经过测试,没有优化标志,我的编译器添加sizeof(int),没有填充
  • @Usiten 这不是针对您的。但这些答案也适用于其他人。这是为了确保没有其他人这样做。并且 sizeof(int) 带有默认值通常适合。如果您使用char 而不是int,它可能会超过sizeof(char)(取决于编译器和CPU)。
  • @Usiten 也经常将virtual 实现放在第一个槽指针到vtable 需要处理(A *) 实例上的虚拟调用,这将立即转移&amp;a.i(但这取决于关于特定编译器如何实现虚函数调用的课程,并且每个平台可能会有所不同,尤其是 32b 与 64b)。 (只需在 zwol 的答案中将 virtual 添加到 A::bar() 即可查看它的实际效果)。
【解决方案2】:

您的程序的这个修改版本及其输出可能会很有启发性。

#include <iostream>
using std::cout;

class A {
public:
  int data;

  struct {
    int data;
    void bar()
    {
      cout << this << '\n';
      cout << &this->data << '\n';
    }
  } foo;

  void bar()
  {
    cout << this << '\n';
    cout << &this->data << '\n';
    cout << &this->foo << '\n';
  }
};

int main(void)
{
  A a;
  cout << &a << '\n';
  a.bar();
  a.foo.bar();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-23
    • 2010-12-31
    • 2017-01-09
    • 2021-10-12
    • 1970-01-01
    相关资源
    最近更新 更多