0

I made an empty class having specific offset and want to derived class using that area..

like below code.. I use alignas()

#include <iostream>
#include <string>
#include <string.h>

using namespace std;

#pragma pack (push, 1)
class alignas(32) base
{
public:
    base() { init(); }
    void init() { memset(this, 0, 32); }
}; // sizeof(base) = 32

class derived01 : public base
{
    int a;
    int b;
}; // sizeof(derived01) = 32

class derived02 : public base
{
    char a[20];
}; // sizeof(derived02) = 32

class item
{
    int a;
    base b;
    int c;

public: 
    template <typename T>
    inline T GetDerived()
    {
        return reinterpret_cast<T>(&b);
    }
};
#pragma pack (pop)

int main()
{
    cout << "ItemUnit :" << sizeof(base) << endl;
    cout << "derived01 :" << sizeof(derived01) << endl;
    cout << "derived02 :" << sizeof(derived02) << endl;

    cout << "item :" << sizeof(item) << endl;

    // I want to get Derived Class like this..
    //item* i = new item();
    //derived02 d = i.GetDerived<derived02>();

    return 0;
}

and, it seemed to work as expected.. In LINUX.. (g++ 7.4)

# ./a
ItemUnit :32
derived01 :32
derived02 :32
item :40

but in MSVS2019, it returned..

ItemUnit :32
derived01 :32
derived02 :32
item :96

I also thought about other ways, but they have some....

  1. UNION but, it cant using inheritance.. and I think it inconvenient to use.

  2. make base class having char[32].. and derived having only functions to get,set using offset..

Is there any other good way? please advice..

  • The size issue is because of [Why isn't sizeof for a struct equal to the sum of sizeof of each member?](https://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct-equal-to-the-sum-of-sizeof-of-each-member) – Some programmer dude Apr 09 '21 at 02:33
  • 1
    Also note that your `item::GetDerived` function will only work correctly for `T` being `base`. Storing any other child-object in `b` will lead to [*object slicing*](https://stackoverflow.com/questions/274626/what-is-object-slicing). Any child-class data will be lost and can't be recreated by this function. – Some programmer dude Apr 09 '21 at 02:35
  • Also note that using *possible* padding space is really bad! There's no guarantee that the compiler might even *add* padding to your classes, in which case the `base::init()` function will write out of bounds of your object. – Some programmer dude Apr 09 '21 at 02:39
  • Lastly, and as a possible way to work around your problems, how about a class hierarchy *without* using the `alignas` specifier, and then put all the classes into a union (together with a 32-byte array to set its size)? – Some programmer dude Apr 09 '21 at 02:43
  • Thank you for answer. yes, compiler(msvs) also say warnings that's dangerous.. and g++ was silent.. Is it the only way to use a union with safety? – dreivok Apr 09 '21 at 02:54
  • When building with GCC, you have enabled extra warnings? Always build with at least `-Wall`. I usually build with `-Wall -Wextra -Wpedantic`. And often use `-Werror` to turn all warnings into errors. – Some programmer dude Apr 09 '21 at 03:00
  • compile with any option.. I use just 'g++ a.cpp -o a' – dreivok Apr 09 '21 at 03:03
  • add with -Wall end Werror it return error just 'unused variable'... – dreivok Apr 09 '21 at 03:06

0 Answers0