C ++ 11: Как получить адрес / ссылку на внешний класс? - PullRequest
3 голосов
/ 15 апреля 2020

Предположим, следующий класс (C ++ 11):

class A
{
  int i;
  class B
  {
    void meth() 
    {
        // Get outer address / reference? 
    }; 
  } b;
};

, где B всегда будет частью A, то есть нет код типа new B().

Это означает, что b.meth() всегда будет работать с внешним A.

Вопрос: Как добраться до внешнего от b.meth() (который всегда имеет такое же смещение b и это известно во время компиляции)?

1 Ответ

3 голосов
/ 15 апреля 2020

Возможно, это не лучшее решение, оно нестандартное, и я уверен, что люди скажут, что это плохая идея. Так что, если вы случайно нашли это на Inte rnet, не используйте его вслепую. Но я не уверен, что стандартное решение даже существует.

Вот оно гласит:

// Example program
#include <iostream>
#include <cstdint>

// This may not be needed if your compiler already has an offsetof macro defined
#ifndef offsetof
#define offsetof(s,m) ((::size_t)&reinterpret_cast<char const volatile&>((((s*)0)->m)))
#endif

class A
{
  public:
  int i;
  class B
  {
    public:
    void meth() 
    {
        // We basically subtract the offset of `b` within `A` from the start of `b`,
        // giving us the outer `A`'s `this`.
        A* outer = (A*)((std::uintptr_t)this - offsetof(A, b));
        std::cout << outer->i;
    }; 
  } b;
};


int main()
{
  A a;
  a.i = 123;
  a.b.meth();

  return 0;
}

// Output: 123

Обратите внимание, что это не удастся, если A не является стандартным типом макета.

В любом случае, я думаю, вам следует подумать о лучшем способе моделирования структуры данных. То, что я написал, это лейкопластырь для вашего немедленного выпуска.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...