Reputation: 1249
I have a C++ class with two virtual functions that use an undefined State
struct either as the return/parameter type. My problem is that the State
structs are only defined in the derived classes and the base class knows nothing about it.
class Base {
// Error: Identifier 'State' is undefined
virtual void serialize(State& last_state) = 0;
virtual State& getCurrentState() = 0;
};
class Derived : public Base {
struct State { // Every derived class has different State fields
int32_t x = 0;
int32_t y = 0;
} current_state;
void serialize(State& last_state) override;
State& getCurrentState() override;
}
Virtual data members aren't a thing, so I'm assuming I just can't define a struct twice. I've also thought that maybe I could create an empty base struct and have every derived classes' State inherit from it, but that doesn't seem like a very clean solution.
Some context for what I'm trying to do in case there's a completely different way this problem could be solved:
I have a map of objects inheriting from Base (std::unordered_map<int, std::shared_ptr<Entity>
). I sometimes loop over the map and want to call serialize()
and getCurrentState()
for each object.
I don't know which derived object I'm accessing, so I can't just cast the base pointer to the derived one. I can't just call a derived classes' members through the base pointer, so what do I do?
Upvotes: 1
Views: 634
Reputation: 5085
Virtual data members aren't a thing, so I'm assuming I just can't define a struct twice. I've also thought that maybe I could create an empty base struct and have every derived classes' State inherit from it, but that doesn't seem like a very clean solution.
That is indeed what you should do. I think it is cleaner, when you declare the base state as a protected class in Base
, so
class Base {
protected:
struct State{};
public:
virtual void serialize(State& last_state) = 0;
virtual State& getCurrentState() = 0;
};
class Derived : public Base {
public:
struct State : Base::State { // Every derived class has different State fields
int32_t x = 0;
int32_t y = 0;
} current_state;
void serialize(Base::State& last_state) override; // Note that the Base:: is important, otherwise the function does not override
State& getCurrentState() override; // You can add Base:: to the return type but you don't have to.
};
Upvotes: 4