sizeof(*this) и наследование структуры

#c #inheritance #struct #sizeof

#c #наследование #структура #sizeof

Вопрос:

Скажем, у меня есть struct что-то вроде следующего:

 struct ParentStruct
{
   virtual void XYZ()
   {
      getSize(sizeof(*this));
   }
   int memberX;
}
 

И другой struct , который наследует родительскую структуру:

 struct ChildStruct : public ParentStruct
{
    int memberY;
    int memberZ;
}
 

Предполагая sizeof(int) == 4 , возможно ли, чтобы значение 12 передавалось функции getSize() при вызове из дочерней структуры (в настоящее время я получаю значение 4)?

Я бы предпочел не перезаписывать XYZ() все подструктуры, так как у меня их будет много.

Ответ №1:

Как говорят другие, тип this — это статический тип класса, в котором он используется. Тем не менее, вы можете выполнить некоторые манипуляции с шаблоном:

 struct Parent{
    virtual void xyz(){ getSize(sizeof(Parent)); }
    int mem1;
};

template<class D>
struct Intermediate : public Parent{
    virtual void xyz(){ getSize(sizeof(D)); }
};

struct Child : public Intermediate<Child>{
    int mem2, mem3;
};
 

Это должно дать желаемый эффект.

Комментарии:

1. virtual void xyz(){ getSize(sizeof(parent)); } Обнять? Чисто виртуальный?

2. @любопытно: почему? У него могут быть простые Parent объекты рядом с дочерними объектами, доступ к которым осуществляется через Parent указатели. Не могу сказать из того, что нам показывают.

3. Правда, нам действительно не хватает контекстуальной информации. (Что, черт возьми, ты пытаешься сделать?)

Ответ №2:

Вы можете использовать шаблоны, чтобы обойти эту проблему:

 template <typename Child>
struct ParentStruct
{
   virtual void XYZ()
   {
      getSize(sizeof(Child));
   }
   int memberX;
}

struct ChildStruct : public ParentStruct<ChildStruct>
{
    int memberY;
    int memberZ;
}
 

Таким образом, вы сообщаете родительской структуре, кем являются ее дочерние элементы — это не очень чистое решение, но оно выполняет работу и позволяет избежать повторения кода getSize.

Комментарии:

1. Но тогда вы не сможете создавать общие вещи, такие как vector, vector<ParentStruct> которые не будут работать без параметра типа. при этом теряется много хорошего в наследовании.

2. @Dani: Просто добавьте супербазу, как в моем примере, и все в порядке.

Ответ №3:

Тип type of this всегда является статическим типом класса, поэтому sizeof(*this) всегда sizeof(ParentStruct) . (Подумайте: как бы sizeof оставалось постоянным выражение, если бы тип this не был статическим?)

Если вы сообщите нам, что вы пытаетесь сделать, мы можем предложить более удобные в обслуживании альтернативы.

Ответ №4:

Я считаю sizeof , что в этом случае известен только размер статического типа *this (т. Е. ParentStruct ), а не его тип во время выполнения ( ChildStruct ). Не имеет значения, что XYZ() здесь объявлено virtual .

Ответ №5:

вы получаете размер базовой структуры, которую вы не перегружали в дочернем элементе

Комментарии:

1. Я не отрицал ваш ответ, но ваш ответ не имеет смысла. Что бы вы перегрузили в дочернем элементе? sizeof ? Вы не можете перегружать это. Кроме того, обычно помогает отвечать полными предложениями.

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

3. Но тогда вам нужно будет дублировать код, что обычно нежелательно.

4. Нет, это НЕ дублирующий код. Подклассы и перегрузка — вот что такое наследование!!!! И поскольку это виртуальный метод, когда вы его перегружаете, вы можете принудительно вызвать подкласс, даже если объект подкласса хранится в родительском указателе.

5. Вам понадобятся две реализации XYZ метода, и тело каждой из них будет одинаковым : getSize(sizeof(*this)); . Как это не дублирует код? Теперь, если бы вы предложили добавить отдельный виртуальный метод, который просто возвращает sizeof *this то, что вы реализовали в базовом и дочернем классах, это было бы лучше (хотя это все равно было бы подвержено ошибкам, поскольку вы полагались бы на каждый производный класс для его переопределения).