#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
то, что вы реализовали в базовом и дочернем классах, это было бы лучше (хотя это все равно было бы подвержено ошибкам, поскольку вы полагались бы на каждый производный класс для его переопределения).