I'm working on a node based structure for defining a creature. Each body part can have "sockets" where you can put things into such as limbs or claws or whatever. To ease future development, it would be good if i could piece together classes from partial ones and have their methods work in conjunction. For instance:
struct Generic {
vector<Generic*> GetSockets() {return vector<Generic*>();}
}
typedef Generic* GenSock;
struct Bipedal {
GenSock LeftLeg;
GenSock RightLeg;
vector<Generic*> GetSockets() {
vector<Generic*> ret;
ret.push_back(RightLeg);
ret.push_back(LeftLeg);
return ret;
}
}
struct TripleHeaded {
GenSock Head1;
GenSock Head2;
GenSock Head3;
vector<Generic*> GetSockets() {
vector<Generic*> ret;
ret.push_back(Head1);
ret.push_back(Head2);
ret.push_back(Head3);
return ret;
}
}
struct CrazyAlienTorso : Generic, Bipedal, Tripleheaded {
vector<Generic*> GetSockets() {
somehow call getsockets from all inherited classes and combine the vector for a single output
}
}
Is that at all possible?
Otherwise I could of course write out the sockets on each leaflet class manually but as I get more specific with the abstraction, this will likely become very tedious.
Maybe something like this would work for you?
struct CrazyAlienTorso : Generic, Bipedal, Tripleheaded {
vector<Generic*> GetSockets() {
vector<Generic*> v1 = Bipedal::GetSockets();
vector<Generic*> v2 = TripleHeaded::GetSockets();
v1.insert(v1.end(), v2.begin(), v2.end());
return v1;
}
}
There is no way (as far as I know, though they might be working on one for a later version of C++) to enumerate all of the direct bases of a class. Aside from that, though, Kupiakos' answer should work well. If you need to do this sort of thing a bunch of times and have tons of base classes that you need to incorporate, you can do a bit of template metaprogramming to get a slightly cleaner shortcut:
template <typename Base, typename... OtherBases>
struct socket_collector {
template <typename Derived>
static void add_sockets(Derived* obj, vector<Generic*>& sockets) {
socket_collector<OtherBases...>::add_sockets(obj, sockets);
auto new_sockets = static_cast<Base*>(obj)->GetSockets();
sockets.insert(end(sockets), begin(new_sockets), end(new_sockets));
}
};
template <typename Base> struct socket_collector<Base> {
template <typename Derived>
static void add_sockets(Derived* obj, vector<Generic*>& sockets) {
auto new_sockets = static_cast<Base*>(obj)->GetSockets();
sockets.insert(end(sockets), begin(new_sockets), end(new_sockets));
}
};
template <typename... Bases, typename Derived>
vector<Generic*> collect_sockets(Derived* obj) {
vector<Generic*> sockets;
socket_collector<Bases...>::add_sockets(obj, sockets);
return sockets;
}
//...
vector<Generic*> CrazyAlienTorso::GetSockets() {
return collect_sockets<Generic, Bipedal, TripleHeaded>(this);
}
Of course, the main question is what the intended use of GetSockets
is: depending on the task that you're trying to accomplish, there might be a better way to structure the code that doesn't involve as much problematic OOP.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.