接續前一篇,C語言列舉(enum)成員的走訪與避免被誤改,補充紀錄sizeof範例
參考資料:
class UTestSizeOfRecordWithoutVirtual
{
protected:
template<int N>
struct StaticRec
{
static constexpr int Value = N;
const int GetValue1() const { return Value; };
int GetValue2() { return GetValue1(); };
};
struct Static5: StaticRec<5>
{
const int GetValue3() const { return Value; };
};
struct Static5B: Static5
{
const int GetValue4() const { return GetValue3(); };
};
struct Static5C: Static5B
{
int Value2 = Value;
};
static constexpr size_t SizeOfStaticRec0 = sizeof(StaticRec<0>) == 1 ? 1 : throw std::logic_error("");
static constexpr size_t SizeOfStaticRecM1 = sizeof(StaticRec<-1>) == 1 ? 1 : throw std::logic_error("");
static constexpr size_t SizeOfStaticRecM5 = sizeof(StaticRec<-5>) == 1 ? 1 : throw std::logic_error("");
static constexpr size_t SizeOfStaticRec1 = sizeof(StaticRec<1>) == 1 ? 1 : throw std::logic_error("");
static constexpr size_t SizeOfStaticRec5 = sizeof(StaticRec<5>) == 1 ? 1 : throw std::logic_error("");
static constexpr size_t SizeOfStatic5 = sizeof(Static5) == 1 ? 1 : throw std::logic_error("");
static constexpr size_t SizeOfStatic5B = sizeof(Static5B) == 1 ? 1 : throw std::logic_error("");
static constexpr size_t SizeOfStatic5BVaule = sizeof(Static5B::Value) == 4 ? 4 : throw std::logic_error("");
static constexpr size_t SizeOfStatic5C = sizeof(Static5C) == 4 ? 4 : throw std::logic_error("");
};
class UTestSizeOfRecordWithVirtual
{
protected:
template<int N>
struct StaticRec
{
static constexpr int Value = N;
const int GetValue1() const { return Value; };
int GetValue2() { return GetValue1(); };
};
struct Static5: StaticRec<5>
{
virtual const int GetValue3() const { return Value; };
};
struct Static5B: Static5
{
virtual const int GetValue4() const { return GetValue3(); };
};
struct Static5C: Static5B
{
int Value2 = Value;
};
static constexpr size_t SizeOfStaticRec0 = sizeof(StaticRec<0>) == 1 ? 1 : throw std::logic_error("");
static constexpr size_t SizeOfStaticRecM1 = sizeof(StaticRec<-1>) == 1 ? 1 : throw std::logic_error("");
static constexpr size_t SizeOfStaticRecM5 = sizeof(StaticRec<-5>) == 1 ? 1 : throw std::logic_error("");
static constexpr size_t SizeOfStaticRec1 = sizeof(StaticRec<1>) == 1 ? 1 : throw std::logic_error("");
static constexpr size_t SizeOfStaticRec5 = sizeof(StaticRec<5>) == 1 ? 1 : throw std::logic_error("");
static constexpr size_t SizeOfStatic5 = sizeof(Static5) == 8 ? 8 : throw std::logic_error("");
static constexpr size_t SizeOfStatic5B = sizeof(Static5B) == 8 ? 8 : throw std::logic_error("");
static constexpr size_t SizeOfStatic5BVaule = sizeof(Static5B::Value) == 4 ? 4 : throw std::logic_error("");
static constexpr size_t SizeOfStatic5C = sizeof(Static5C) == 16 ? 16 : throw std::logic_error("");
};
參考資料其實有看沒有懂,但是範例程式碼有無virtual,對於sizeof(Static5C)的影響會很大,難以理解
而且範例程式碼在不同平台(Windows/Linux/AIX7/...?)上結果一樣!很神奇
總之,團隊開發或是有甲乙方不同腳色的專案開發,別認為在改版時,
只是為struct或class內方法加上virtual,或是移除virtual,
不會對其他開發成員造成影響,其實有可能是埋地雷引發災難!
20240908補充
加上pragma pack(1),sizeof(Static5C)會變成12
pragma pack(8),sizeof(Static5C)會變成16
#pragma pack(1)
class UTestSizeOfRecordWithVirtualAndPack1
{
protected:
template<int N>
struct StaticRec
{
static constexpr int Value = N;
const int GetValue1() const { return Value; };
int GetValue2() { return GetValue1(); };
};
struct Static5: StaticRec<5>
{
virtual const int GetValue3() const { return Value; };
};
struct Static5B: Static5
{
virtual const int GetValue4() const { return GetValue3(); };
};
struct Static5C: Static5B
{
int Value2 = Value;
};
static constexpr size_t SizeOfStaticRec0 = sizeof(StaticRec<0>) == 1 ? 1 : throw std::logic_error("");
static constexpr size_t SizeOfStaticRecM1 = sizeof(StaticRec<-1>) == 1 ? 1 : throw std::logic_error("");
static constexpr size_t SizeOfStaticRecM5 = sizeof(StaticRec<-5>) == 1 ? 1 : throw std::logic_error("");
static constexpr size_t SizeOfStaticRec1 = sizeof(StaticRec<1>) == 1 ? 1 : throw std::logic_error("");
static constexpr size_t SizeOfStaticRec5 = sizeof(StaticRec<5>) == 1 ? 1 : throw std::logic_error("");
static constexpr size_t SizeOfStatic5 = sizeof(Static5) == 8 ? 8 : throw std::logic_error("");
static constexpr size_t SizeOfStatic5B = sizeof(Static5B) == 8 ? 8 : throw std::logic_error("");
static constexpr size_t SizeOfStatic5BVaule = sizeof(Static5B::Value) == 4 ? 4 : throw std::logic_error("");
static constexpr size_t SizeOfStatic5C = sizeof(Static5C) == 12 ? 12 : throw std::logic_error("");
};
#pragma pack()
#pragma pack(8)
class UTestSizeOfRecordWithVirtualAndPack8
{
protected:
template<int N>
struct StaticRec
{
static constexpr int Value = N;
const int GetValue1() const { return Value; };
int GetValue2() { return GetValue1(); };
};
struct Static5: StaticRec<5>
{
virtual const int GetValue3() const { return Value; };
};
struct Static5B: Static5
{
virtual const int GetValue4() const { return GetValue3(); };
};
struct Static5C: Static5B
{
int Value2 = Value;
};
static constexpr size_t SizeOfStaticRec0 = sizeof(StaticRec<0>) == 1 ? 1 : throw std::logic_error("");
static constexpr size_t SizeOfStaticRecM1 = sizeof(StaticRec<-1>) == 1 ? 1 : throw std::logic_error("");
static constexpr size_t SizeOfStaticRecM5 = sizeof(StaticRec<-5>) == 1 ? 1 : throw std::logic_error("");
static constexpr size_t SizeOfStaticRec1 = sizeof(StaticRec<1>) == 1 ? 1 : throw std::logic_error("");
static constexpr size_t SizeOfStaticRec5 = sizeof(StaticRec<5>) == 1 ? 1 : throw std::logic_error("");
static constexpr size_t SizeOfStatic5 = sizeof(Static5) == 8 ? 8 : throw std::logic_error("");
static constexpr size_t SizeOfStatic5B = sizeof(Static5B) == 8 ? 8 : throw std::logic_error("");
static constexpr size_t SizeOfStatic5BVaule = sizeof(Static5B::Value) == 4 ? 4 : throw std::logic_error("");
static constexpr size_t SizeOfStatic5C = sizeof(Static5C) == 16 ? 16 : throw std::logic_error("");
};
#pragma pack()