Можно ли предположить, что в классе без виртуальных методов или суперкласса (адрес первой переменной-члена) == this? - PullRequest
4 голосов
/ 12 апреля 2010

Я создал частный API, который предполагает, что адрес первого объекта-члена в классе будет таким же, как у указателя this класса ... таким образом, объект-член может тривиально получить указатель на объект, который он является членом, без необходимости явно хранить указатель.

Учитывая, что я хочу убедиться, что контейнерный класс не будет наследоваться от какого-либо суперкласса, не будет иметь никаких виртуальных методов, и что объект-член, который выполняет этот трюк, будет первым объявленным объектом-членом, это предположение считается действительным для любого компилятора C ++, или мне нужно использовать оператор offsetof () (или аналогичный), чтобы гарантировать правильность?

Другими словами, приведенный ниже код выполняет то, что я ожидаю от g ++, но будет ли он работать везде?

class MyContainer
{
public:
   MyContainer() {}
   ~MyContainer() {}  // non-virtual dtor

private:
   class MyContained
   {
   public:
      MyContained() {}
      ~MyContained() {}

      // Given that the only place Contained objects are declared is m_contained
      // (below), will this work as expected on any C++ compiler?
      MyContainer * GetPointerToMyContainer()
      {
         return reinterpret_cast<MyContainer *>(this);
      }
   };

   MyContained m_contained;  // MUST BE FIRST MEMBER ITEM DECLARED IN MyContainer
   int m_foo;                // other member items may be declared after m_contained
   float m_bar;
};

Ответы [ 3 ]

5 голосов
/ 12 апреля 2010

Кажется, текущий стандарт гарантирует это только для типов POD.

9.2.17

Указатель на объект POD-struct, соответствующим образом преобразован, указывает на его первоначальный член (или если этот член битовое поле, то к единице, в которой оно проживает) и наоборот. [Заметка: Поэтому может быть безымянным заполнение внутри объекта POD-struct, но не в начале, по необходимости добиться соответствующего выравнивания. ]

Однако стандарт C ++ 0x, похоже, расширяет эту гарантию до «объекта структуры стандартного макета»

Стандартный макет класса что:

- не содержит нестатических данных членов тип нестандартного макета класса (или массив таких типов) или ссылка,

- не имеет виртуальных функций (10.3) и нет виртуальных базовых классов (10.1),

- имеет тот же контроль доступа (пункт 11) для всех нестатических элементов данных,

- не имеет нестандартной компоновки базы классы,

- либо нет нестатических данных члены в наиболее производном классе и не более одного базового класса с нестатическим члены данных, или не имеет базовых классов с нестатическими элементами данных и

- не имеет базовых классов того же типа как первый нестатический элемент данных.

Стандартная структура макета класс макета, определенный с структура ключа класса или ключ класса класс.

Вероятно, что предположение справедливо на практике (а у первого не было только этих различий, хотя это могло быть намерением)?

3 голосов
/ 12 апреля 2010

Это не гарантируется для типов без POD. Стандарт C ++ 9.2 / 12:

Нестатические данные членов (не объединенный) класс, объявленный без промежуточный спецификатор доступа так что более поздние члены имеют более высокие адреса в классе объект. Порядок выделения нестатические члены данных, разделенные спецификатор доступа не указан (11.1). Выравнивание реализации требования могут привести к двум соседние члены не подлежат распределению сразу после друг друга; так может требования к пространству для управления виртуальные функции (10.3) и виртуальные базовые классы (10.1).

В вашем случае у вас есть не POD тип, так как он содержит пользовательский деструктор. Подробнее о типах POD вы можете прочитать здесь .

2 голосов
/ 12 апреля 2010

В последнем проекте спецификации C ++ говорится, что это нормально, если класс квалифицируется как стандартный класс макета , для которого просто требуется

  • не имеет нестатических членов-данных типа нестандартного класса (или массива таких типов) или ссылки,
  • не имеет виртуальных функций (10.3) и виртуальных базовых классов (10.1),
  • имеет одинаковое управление доступом (пункт 11) для всех нестатических элементов данных,
  • не имеет базовых классов нестандартной компоновки,
  • либо не имеет нестатических членов-данных в самом производном классе, но не более одного базового класса с нестатические члены данных или не имеет базовых классов с нестатическими членами данных, и
  • не имеет базовых классов того же типа, что и первый нестатический элемент данных.

В зависимости от определения MyContained, ваш класс может быть или не быть стандартным макетом

Обратите внимание, что POD-классы являются пересечением стандартного макета и , легко копируемых классов

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