C++ 随机类的宏

C++ 随机类的宏,c++,c-preprocessor,C++,C Preprocessor,我有一个包含多个子类的父类,并打算添加一个函数,该函数随机生成并返回指向其中一个子类的指针。例如 class Parent { ... } class Child1 : public Parent {...} class Child2 : public Parent {...} ... class ChildN : public Parent {...} // returns one of the children, randomly Parent* generate_random(); 一

我有一个包含多个子类的父类,并打算添加一个函数,该函数随机生成并返回指向其中一个子类的指针。例如

class Parent { ... }
class Child1 : public Parent {...}
class Child2 : public Parent {...}
...
class ChildN : public Parent {...}

// returns one of the children, randomly
Parent* generate_random();
一方面,我可以编写
generate_random
硬编码子类的数量,并在每次添加父类的新子类或删除旧子类时更新该数量。但这似乎有点脆弱。类似地,我甚至可以使用const变量来跟踪子类的数量。同样,每当添加和删除类时,我都必须手动更新它。这似乎也很脆弱

相反,在Python这样的语言中,我可能会在父类的每个子类的声明上方放置一个装饰器,这将增加所有子类的计数并使用它。例如:

_num_subclasses = 0
def _register_subclass(cls):
    global _num_subclasses
    _num_subclasses += 1

class Parent(object):
    ...

@_register_subclass
class Child1 (Parent):
    ...
@_register_subclass
class Child2 (Parent):
    ...
...

有没有一种方法可以使用预处理器做类似的事情?或者有没有一种方法可以在类声明之前或之后运行一次方法?(如果我不仅可以为每个类增加一个计数器,还可以在单例映射中为它注册一个工厂,那就太好了。)或者,更一般地说,其他人如何处理这类问题?如果我的问题不清楚或需要重新表述,请告诉我。

我对python一无所知,但让我们检查一下:

_num_subclasses = 0
def _register_subclass(cls):
    global _num_subclasses
    _num_subclasses += 1

@_register_subclass
class Child1 (Parent):
并将其转换为C++(ish)


为什么不使用模板或有更好的设计?我会选择最近的问题,因为这个问题可能还不清楚。我一点也不支持这种特殊的设计。我通常会问,提供此功能的惯用干净方法是什么。或者,更简洁地说,“我现在所做的似乎很糟糕,什么是更好的设计?”如果您对更好的设计或参考有想法,我会非常感激。目前还不清楚您想要实现什么。EC++有一个预定义的宏,名为[COUNTER][1],您可以使用它。[1] :qwerty,我不知道计数器。非常感谢。你说得对,那可能会让我大部分时间都在那里。下面的MooingDuck解决方案更加优雅和通用(允许创建工厂等),我建议其他人在下面查看。MooingDuck,这几乎正是我一直在寻找和努力解决的问题。我想我没有意识到我可以在作业中使用副作用来模仿装饰师。非常感谢。我要接受这个答案。但是,你能澄清一下你所说的建议使用枚举的意思吗?似乎typeid做了它需要做的事情,它的优点是每当我添加和删除一个类时,不需要在多个地方修改代码(使用枚举,我修改枚举和我实际声明类的地方)。再次感谢您。@BehramMistree:枚举允许您从0-N中对N个派生类进行编号,这样可以方便地进行迭代,并且很容易随机选择一个派生类。然而,我想你说你不能(不会)那样做,那很好
type_info
应该可以正常工作,但是随机选择一个会有点困难。我已经在回答中解释了如何做到这一点。
int _num_subclasses = 0;
template<class cls>
bool _register_subclass() {
    _num_subclasses += 1;
    return true;
}

class Child1 : public Parent {
};
static const bool register1 = _register_subclass<Child1>();
typedef std::unique_ptr<Parent*> ParentPointer;
//an enum is recommended, but type_id can work, depending on what you're doing
std::unordered_map<std::type_info, std::function<ParentPointer()>> _subclass_generator;
template<class cls>
bool _register_subclass() {
    _subclass_generator[typeid(cls)] = 
        []()->ParentPointer{
            return ParentPointer(new cls{});
        };
    return true;
}

class Child1 : public Parent {
};
static const bool register1 = _register_subclass<Child1>();
int selection = std::rand() % _subclass_generator.size();
auto& generator = *std::advance(_subclass_generator.begin(), selection);
ParentPointer ptr = generator(); //generates a Child.