Robiąc "rejestr tworzonych obiektów", skazujesz się na konieczność ustosunkowania się co do czasu ich życia. Np. co zrobić jeśli zostaną zniszczone? Jak (a raczej kiedy) wyrejestrować je z kontenera? Gdzie trzymać kontener?
Raczej zrobił bym to z użyciem CRTP: https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Curiously_Recurring_Template_Pattern
To dany obiekt powinien zapytać o stan pewnej wspólnej zmiennej. Tu przyjąłem że poprzez dziedziczenie określisz jakie rodziny o jakie zmienne pytają. W przykładzie zakładałem że będą komnaty w których magia nie działa. Wszystkie obiekty typu MagicArtifact powinny wtedy utracić właściwość czarowania. Mimo to dalej są artefaktami :-)
Szybki przykład przedstawiający ten sposób...
#include <iostream>
template<typename T>
class Working {
public:
static void setWork(bool w) {
isWork = w;
}
static bool isWorking() {
return Working<T>::isWork;
}
private:
static bool isWork;
};
template<typename T>
bool Working<T>::isWork = true;
class Artifact {
public:
virtual void doWork() = 0;
virtual ~Artifact() {};
};
class Card : public Artifact, public Working<Artifact> {
public:
void doWork() override {
std::cout << "Card doWork() working = " << std::boolalpha
<< Working<Artifact>::isWorking() << '\n';
}
};
class MagicArtifact: public Artifact, public Working<MagicArtifact> {
public:
void doWork() override {
std::cout << "Magic Artifact doWork() working = " << std::boolalpha
<< Working<MagicArtifact>::isWorking() << '\n';
}
};
class Wand : public Artifact, public Working<MagicArtifact> {
public:
void doWork() override {
std::cout << "Wand doWork() working = " << std::boolalpha
<< Working<MagicArtifact>::isWorking() << '\n';
}
};
class Elixir: public Artifact, public Working<MagicArtifact> {
public:
void doWork() override {
std::cout << "Elixir doWork() working = " << std::boolalpha
<< Working<MagicArtifact>::isWorking() << '\n';
}
};
int main() {
Card c;
Wand w;
Elixir e;
// Do testów więc w trybie "spagetti" :-)
std::cout << "Artifact <- true, MagicArtifact <- false\n";
Working<Artifact>::setWork(true);
Working<MagicArtifact>::setWork(false);
c.doWork();
w.doWork();
e.doWork();
std::cout << "Artifact <- false, MagicArtifact <- true\n";
Working<Artifact>::setWork(false);
Working<MagicArtifact>::setWork(true);
c.doWork();
w.doWork();
e.doWork();
}
Nawet mógłbyś nie dziedziczyć tylko wołać określone rodzaje wspólnych zmiennych. Być może będziesz chciał sprawdzać typ, stąd relacja dziedziczenia klasycznego CRTP :-)
Dodatkowo pozwoli Ci to np. implementować takie zachowania w logice gdzie "jeśli w klasie Wand (która jest typu Artifact i także MagicArtifact) Artifact nie działa to nie jest ważne czy MagicArtifact działa a jak Artifact działa to istotne jest czy MagicArtifact działa" :-)