Если это поможет, вы можете взять ответ Хитеша и добавить:
struct luaRegisterManager {
template <typename T>
void registrate() {
T::registrate();
// do something else to record the fact that we've registered -
// perhaps "registrate" should be returning some object to help with that
}
};
Затем:
int main() {
luaRegisterManager lrm;
lrm.registrate<someClass>();
lrm.registrate<someOtherClass>();
}
В целом, если вы хотите ввести какой-либо динамический полиморфизм в C ++,тогда вам нужен объект, а не просто класс.Итак, еще раз, возможно, различные функции register
должны возвращать объекты с некоторым базовым интерфейсом базового класса registeredClass
, или classRegistrationInfo
, или что-то в этом роде.
Может привести пример того, что вы чувствуетеэто для чего нужен динамический полиморфизм?Насколько я вижу, код Hitesh точно соответствует вашему единственному примеру, поэтому этот пример не должен охватывать все ваши ожидаемые варианты использования.Если вы напишете код, который будет использовать его, возможно, вам станет ясно, как его реализовать, или, возможно, кто-то посоветует.
Что-то еще, что может помочь:
#include <iostream>
#include <string>
#include <vector>
struct Registered {
virtual std::string name() = 0;
virtual ~Registered() {}
Registered() {
all.push_back(this);
}
static std::vector<Registered*> all;
};
std::vector<Registered*> Registered::all;
typedef std::vector<Registered*>::iterator Iter;
template <typename T>
struct RegisteredT : Registered {
std::string n;
RegisteredT(const std::string &name) : n(name) { T::registrate(); }
std::string name() { return n; }
// other functions here could be implemented in terms of calls to static
// functions of T.
};
struct someClass {
static Registered *r;
static void registrate() { std::cout << "registering someClass\n"; }
};
Registered *someClass::r = new RegisteredT<someClass>("someClass");
struct someOtherClass {
static Registered *r;
static void registrate() { std::cout << "registering someOtherClass\n"; }
};
Registered *someOtherClass::r = new RegisteredT<someOtherClass>("someOtherClass");
int main() {
for (Iter it = Registered::all.begin(); it < Registered::all.end(); ++it) {
std::cout << (*it)->name() << "\n";
}
}
С этим кодом возникают всевозможные проблемы, если вы попытаетесь разделить его на несколько модулей компиляции.Кроме того, такого рода вещи приводят к ложным отчетам от детекторов утечки памяти, если вы не написали какой-то код, чтобы все разрушить в конце, или использовали вектор shared_ptr
, вектор указателя усиления и т. Д. Но вы видите общую идею, чтокласс может «регистрировать себя», и вам нужен объект для виртуальных вызовов.
В C ++ вы обычно стараетесь избегать статической инициализации, хотя в пользу какого-либо внедрения / установки зависимостей в началевашей программы.Поэтому обычно вы просто перечисляете все классы, которые вам нужны (вызывая функцию для каждого из них), а не пытаетесь сделать это автоматически.