0

Hello everyone,

I have a simple struct C which contains 3 variables. Then I have two structs, A and B, where B is derived from A. All in all, B contains the same 3 types of variables as in my simple struct C.

(Note: C++ structs are used)

My questions:

  1. Can I cast between C and B as in my example below, i.e. is it allowed or do I have to look at something special (memory)? My example below produces no valgrind mem error. However, I want to be sure what you think about it.
  2. Am I right, that if B inherits from A, the variables from struct A are put before (or afterwards - depending on architecture) the variables of B in memory, i.e. do I have everytime an "ordered" memory which fits to struct C ordering/memory? Or can it happen, that e.g. the "type" variable from A is between the "str" and "value" variable?

Hope you can help me! Thanks in advance.

Example (C++11 style):

#include <memory>
#include <string>
#include <iostream>

struct a
{
    unsigned int type;

    a(unsigned int t) : type(t)
    {}
};

struct b : public a
{
    std::string str;
    unsigned int value;

    b() : a(2), str("Hello"), value(1)
    {}
};

struct c
{
    unsigned int type;

    std::string str;
    unsigned int value;

    c() : type(1), str("World"), value(42)
    {};
};

int main(int argc, char*argv[])
{
    // Bottom up
    {
        std::cout << "Bottom Up" << std::endl;

        c* ptr2 = new c();

        std::cout << ptr2->type << std::endl;
        std::cout << ptr2->str << std::endl;
        std::cout << ptr2->value << std::endl;

        std::shared_ptr<b>ptr;
        ptr.reset(reinterpret_cast<b*>(ptr2));

        std::cout << ptr->type << std::endl;
        std::cout << ptr->str << std::endl;
        std::cout << ptr->value << std::endl;
        std::cout << std::endl;
    }

    // Top down
    {
        std::cout << "Top down" << std::endl;
        std::shared_ptr<b>ptr(new b());

        std::cout << ptr->type << std::endl;
        std::cout << ptr->str << std::endl;
        std::cout << ptr->value << std::endl;

        c* ptr2 = reinterpret_cast<c*>(ptr.get());

        std::cout << ptr2->type << std::endl;
        std::cout << ptr2->str << std::endl;
        std::cout << ptr2->value << std::endl;
    }


    return 0;
}
  • If all of the structs are POD (see above link) then it would be safe(r) to do this, but the second they aren't, this is undefined behavior. For example you have inheritance (and therefore a v-table), user defined constructors, non-POD members, etc. So your example will not work. – Cory Kramer May 24 '17 at 17:45
  • The classes in the example are not virtual, so there are no v-tables. – Özgür Murat Sağdıçoğlu May 24 '17 at 17:50
  • Hello, yes in my case, I do *not* have any virtual functions. - Thanks for that Link! –  May 27 '17 at 09:44

0 Answers0