Here is the class hierarchy that I have.
class EventA {/* adds itself to list */};
class EventB {/* adds itself to list */};
class EventC {/* adds itself to list */};
class EventD {/* adds itself to list */};
class EventE {/* adds itself to list */};
class EventF {/* adds itself to list */};
class EventG {/* adds itself to list */};
class EventH {/* adds itself to list */};
class Component : public EventA, public EventB, public EventC, public EventD {
// Propeties and functions
bool sentinel;
};
class CustomComponent : public Component {
// Propeties and functions
};
class UserComponent : public CustomComponent, public EventE, public EventF, public EventG, public EventH {
// Propeties and functions
};
I have a list of each type: EventE
, EventF
, EventG
, EventH
. They are added to the list through the constructor when I create the UserComponent
object. The problem that I am running into is that when I iterate through the list of EventE
, EventF
, EventG
and EventH
, when I cast the pointer from either EventE
, EventF
, EventG
or EventH
to Component*
some of the properties are not correct when interpreted as such a pointer. For example, sometimes my bool sentinel
value will be true(216)
when they are supposed to be false
. My suspicion is that when I convert the pointer, it does not offset the memory to match the class hierarchy that I have laid out. In other words, I think it is not reading from correct memory address. Is anyone familiar with this issue? My problem is at system design level, so any off-topic solution, or any solution that has a different approach are welcome.
Response to Requested Minimal Example
This code is a minimal example of the problem that I am having. I provided it as requested in the comment section.
#include <iostream>
using namespace std;
class EventA {
public:
char a;
EventA() {
a = 'a';
}
~EventA() {
}
};
class EventB {
public:
char b;
EventB() {
b = 'b';
}
~EventB() {
}
};
class EventC {
public:
char c;
EventC() {
c = 'c';
}
~EventC() {
}
};
class EventD {
public:
char d;
EventD() {
d = 'd';
}
~EventD() {
}
};
class EventE {
public:
char e;
EventE() {
e = 'e';
}
~EventE() {
}
};
class EventF {
public:
char f;
EventF() {
f = 'f';
}
~EventF() {
}
};
class EventG {
public:
char g;
EventG() {
g = 'g';
}
~EventG() {
}
};
class EventH {
public:
char h;
EventH() {
h = 'h';
}
~EventH() {
}
};
class Component : public EventA, public EventB, public EventC, public EventD {
public:
int customValue;
Component() {
customValue = 1000;
}
~Component() {
}
};
class CustomComponent : public Component {
public:
int customComponentValue;
CustomComponent() {
customComponentValue = 2000;
}
~CustomComponent() {
}
};
class UserComponent : public CustomComponent, public EventE, public EventF, public EventG, public EventH {
public:
int userComponentValue;
UserComponent() {
userComponentValue = 3000;
}
~UserComponent() {
}
};
int main() {
UserComponent userComponent = UserComponent();
EventE* ptrEventE = (EventE*)&userComponent;
Component* ptrComponent = (Component*)ptrEventE;
cout << ptrComponent->customValue << endl;
}
If you go into debug mode and inspect the value of ptrComponent
you will see exactly what I am talking about. Note that the casting that I made is exactly what is going on at different points of my system. That is why I did it the way I did.
CodePudding user response:
The error is caught if you use static_cast
instead of a C-style cast:
a.cpp: In function 'int main()':
a.cpp:134:31: error: invalid 'static_cast' from type 'EventE*' to type 'Component*'
134 | Component* ptrComponent = static_cast<Component*>(ptrEventE);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
EventE
is not a base of Component
, so the compiler does not know how the two are connected. In your case, they're connected by the common derived UserComponent
, by there may be other common derived classes with different layouts as well, so it's of no help. static_cast
throws an error in that case, C-style cast just does reinterpret_cast
and assumes that no pointer modifications are needed.
Two ways to fix: either make Component
derive from EventE
as well or cast through a known common derived class:
int main() {
UserComponent userComponent = UserComponent();
EventE* ptrEventE = static_cast<EventE*>(&userComponent);
Component* ptrComponent = static_cast<UserComponent*>(ptrEventE); // UserComponent --> Component is implicit
cout << ptrComponent->customValue << endl;
}