Polymorphism Bug

I am trying to do some simple polymorphic code, but when calling parent objects, the passed pointer dereferences to an empty data structure. This is something that should "just work", but it isn't.

trimmed down code of the problem:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>
#include <string>
using namespace std;
class Command
{
public:
static const unsigned int sort_order = 0;
virtual string format() = 0;
template< class Right >
bool operator< (Right& right) { return sort_order < right.sort_order; } 
};
class Definition : public Command
{
DataMemberStruct _data;
public:
static const unsigned int sort_order = 1;
Definition(DataMemberStruct& data) {_data = data;}
virtual string format() 
{if(_data.init)
 cout << "Print generic data struct \n";
else
 cout << "Print error\n";}
};
class DefineObject : public Definition
{
DataMemberStruct _data;
public:
static const unsigned int sort_order = 2;
DefineObject(DataMemberStruct&  data) {_data = data;}
virtual string format() 
{
if(_data.object && _data.init)
 cout << "Print object data struct \n";
else if (_data.init)
 cout << Definition::format();
else
 cout << "Print error\n";
}
};


However, when I make a Command* command = new DefineObject(data). and _data.init = true but _data.object = false (so it falls back on the parent object's definition) I get out:

Print error

Because the _data structure has empty members (which I can check in gdb). What the heck is going on? For some reason a Definition* const pointer dereferencing _data from a DefineObject* const pointer is empty even though the classes have the same memory structure? (There's some more to format than what I included, but I wanted to keep the problem simpler)
What's happening is that there's two objects named '_data' in each DefineObject. One is DefineObject::_data, and the other is Definition::_data. When you're constructing DefineObject, you're only initializing DefineObject::_data. The other one is left with garbage.

Either remove one of the objects -- preferably DefineObject::_data, while making the other one protected -- or call the base constructor in DefineObject::DefineObject().

PS: Oh, and please leave less spacing in the code. It's right there on the high end of "unreadable mess", but I think if you apply yourself, you get it all the way up to "clusterfuck".
Last edited on
Topic archived. No new replies allowed.