作者热门文章
- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我想知道是否存在自动注册类类型的设计模式或习语。或者更简单,我可以通过简单地扩展基类来强制调用某个类的方法吗?
例如,假设我有一个基类 Animal
和扩展类 Tiger
和 Dog
,并且我有一个打印输出的辅助函数所有扩展Animal
的类。
所以我可以有类似的东西:
struct AnimalManager
{
static std::vector<std::string> names;
static void registerAnimal(std::string name) {
//if not already registered
names.push_back(name); }
};
struct Animal
{
virtual std::string name() = 0;
void registerAnimal() { AnimalManager::registerAnimal(name()); }
};
struct Tiger : Animal
{
virtual std::string name() { return "Tiger"; }
};
所以基本上我会这样做:
Tiger t;
t.registerAnimal();
这也可以用于 static
函数。是否有任何模式(如奇怪的递归模板)或类似的东西可以帮助我实现这一点,而无需显式调用 registerAnimal
方法。
我希望我的 class Animal
将来可以扩展,而其他人可能会忘记调用 register
,我正在寻找防止这种情况的方法除了记录这个(无论如何我都会这样做)。
PS 这只是一个例子,我实际上并没有实现动物。
最佳答案
您确实可以使用奇怪的递归模板习语来做到这一点。它不需要任何扩展编译器无法强制执行的类的人:
template<class T>
struct Animal
{
Animal()
{
reg; //force specialization
}
virtual std::string name() = 0;
static bool reg;
static bool init()
{
T t;
AnimalManager::registerAnimal(t.name());
return true;
}
};
template<class T>
bool Animal<T>::reg = Animal<T>::init();
struct Tiger : Animal<Tiger>
{
virtual std::string name() { return "Tiger"; }
};
在这段代码中,你只能扩展 Animal
如果你专门它。构造函数强制初始化static
成员reg
,然后调用register方法。
编辑:正如@David Hammen 在评论中指出的那样,您将无法拥有 Animal
对象的集合。但是,这可以通过使用模板继承的非模板类并将其用作基类并仅使用模板进行扩展来轻松解决。
关于c++ - 如何在创建时自动注册一个类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10332725/
我是一名优秀的程序员,十分优秀!