0

I have a factory that creates structs that are all derived from a base struct, and these structs all have default values for certain members. When I add the object to a vector of pointers of base type, it seems to reset to the base member data. The object are still intact and I can access derived members, but type has the base value when referenced from the container.

struct a {
    unsigned int type = 0;
};

struct b : a {
    unsigned int type = 1;
};


std::vector<a *> container;

b * message = new b;

container.push_back(message);

message->type is 1

container[0]->type is 0

I've tried casting in different ways when I push into the vector to no avail

Keith
  • 13
  • 2

1 Answers1

0

What this code actually does:

struct a {
    unsigned int type = 0;
};

struct b : a {
    unsigned int type = 1;
};

is it leaves b having two type members, namely a::type and b::type, one hiding the other. Member variables cannot be overridden or virtual in the same sense as member functions. When you access message (whose type is b) through a pointer to a, the compiler can only see a::type, leading to the results you observe. See here for more discussion about overriding member variables. If your design is limited to a single type member, you can make the following simple change:

struct a {
    a(unsigned int _type = 0) : type(_type) {} // default constructor initializes type to 0
    unsigned int type;
};

struct b : a {
    b() : a(1) {} // default constructor initializes inherited type to 1
    // no ambiguous 'type' member here
};

If, however, you need to perform complex logic depending on arbitrary subtypes, you'd best start learning about virtual member functions

alter_igel
  • 6,899
  • 3
  • 21
  • 40
  • I have it set up this way because different messages have different members associated with them, but they all derive from a base struct for things like the type (which the system would test and then pass on appropriately). It looks like my best bet is to use virtual functions as you mentioned. However is there any reason (simply bad practice?) to not have my factory just set a::type to the value of b::type? – Keith Aug 15 '18 at 01:18
  • @Keith because `b::type` is redundant and shouldn't exist at all. Let `b` inherit the `type` member from `a`. The factory can still assign a value to `type` regardless of which class it constructs, if you don't want to handle the assignment of `type` in the constructors. – Remy Lebeau Aug 15 '18 at 04:04