Jestem starym kolesiem, który stara się nauczyć o C++ 11, przenosząc moją starą strukturę stanu maszyny z C do C++ 11. Moim pomysłem jest posiadanie klasy dla samego stanu-maszyny, a następnie zagnieżdżenie klas dla stanów wewnątrz. Stany mogą być hierarchiczne, tj. Super- i podstanowe. Framework musi wiedzieć o super stanie stanu, a do tego mam wskaźnik (state *superstate
) w zagnieżdżonej klasie stanu.C++ 11 Niestatyczna inicjalizacja jednolitego elementu danych kończy się niepowodzeniem dla wskaźników do innych klas tej samej klasy bazowej.
Mój problem polega na tym, że miałem zamiar ustawić superstate-pointer za pomocą konstruktora bezpośrednio w klasie maszyny, co powinno być możliwe w C++ 11 przy niestatycznym inicjowaniu elementu danych, za pomocą jednolitej inicjalizacji. Ale z jakiegoś powodu nie kompiluje się (substateB3{superstateA}
) po ustawieniu na inny typ stanu/klasy. Ale działa dobrze, jeśli później ustawić go za pomocą konkretnej funkcji (set_superstate
) do tego celu, który ma ten sam argument, co konstruktor! I zabawne, że konstruktor jest akceptowany, jeśli ustawię super stan na stan/klasę tego samego typu (substateB2{substateB1}
).
Używam gcc 4.7.0 (aby uzyskać poparcie dla non-statycznych inicjalizatorów członkowskich danych) i tu jest mój kod:
// My state-machine framework (simplified)
struct machine {
struct state {
state() : superstate(nullptr) { } // No superstate => toplevel state!
state(state &superstate) : superstate(&superstate) { }
state *superstate;
void set_superstate(state &superstate) { this->superstate = &superstate; } // Non-ctor way to set superstate
};
};
// An example of a specific state-machine using my framework
struct Machine : machine {
struct SuperstateA : state {
} superstateA;
struct SubstateB : state {
} substateB1, // Compiles OK; gets its superstate set in Machine's ctor below
substateB2{substateB1}, // Compiles OK; but not correct superstate
substateB3{superstateA}; // gcc 4.7.0 error: could not convert ‘{((Machine*)this)->Machine::superstateA}’ from ‘<brace-enclosed initializer list>’ to ‘Machine::SubstateB’
Machine() { substateB1.set_superstate(superstateA); } // Compiles OK;
} myMachine;
Wszelkie wskazówki i wytyczne są bardzo cenione dzięki! :)
Rozumiem, że jest to ćwiczenie do nauki, ale warto przynajmniej przyjrzeć się istniejącej nowoczesnej strukturze maszyn stanu C++, takiej jak [Boost.MSM] (http://www.boost.org/libs/msm/) z pewnej perspektywy. – ildjarn
W C++, nigdy nie należy definiować typu i obiektu tego samego typu w tej samej instrukcji. To bardzo mylące do czytania i jednoznaczne. –
Wygląda na to, że potrzebujesz również dziedziczenia konstruktorów dla 'SubstateB'. Nie jestem pewien, czy GCC obsługuje już takie. –