例如,我有基类A和子类B1,B2,B3等。
我想写一些类似的东西(或其他方式来做,这没关系):
A *randomobject1;
randomobject1 = A::Getrandomobject();
randomobject1是指向随机子类的对象的指针。
我不知道怎么做!也许我需要存储对子方法的引用并在之后调用它,或者......我不明白。
我不需要真正的随机,我需要在生成对象之前知道一些信息。
例如,子类包含带有一些整数的静态字段。我需要从包含这个整数的随机子类生成对象,它是> 30(或与另一种类型的领域)。 所以,有一些整数的类< 30将不会参与世代。
答案 0 :(得分:1)
我假设您的getRandomObject
函数中已知所有可能的子类,并且您希望在每次调用时创建一个新实例。那么这是一个可行的解决方案:
A *getRandomObject() {
int r = getRandomIntInRange(0, 3); // Some method returning a random int from [0,1,2]
switch (r) {
case 0: return new B1();
case 1: return new B2();
case 2: return new B3();
default: return NULL; // should never come here...
}
<强>更新强>
如果您的方法可能不知道所有可能的子类,则可能存在注册机制,您可以存储返回新实例(工厂)的函数。
快速概述:
// Somewhere in your code
A *b1Factory() { return new B1(); }
A *b2Factory() { return new B2(); }
A *b3Factory() { return new B3(); }
// somewhere you have a factory list
typedef A* (*aSubclassFactoryFunc) (void);
std::vector<aSubclassFactoryFunc> factories;
A *getRandomObject() {
int r = getRandomIntInRange(0, factories.size()); // Some method returning a random int from [0,1,2,...,factories.size()]
return factories[r](); // Call random factory
}
新的子类只需将工厂方法添加到工厂列表中。
更新2 :
注册机制可以这样做:
#define REGISTER_A(B) \
struct b_subclass_register_##B {\
b_subclass_register_##B() {\
registerASubclass(b_subclass_register_##B::create);\
}\
static A *create() { return new B; }\
} dummy_instance_##B;
这是一个创建结构并在全局范围内创建虚拟实例的makro。在其构造函数中,子类已注册。
您可以在子类CPP文件中使用它,例如:
REGISTER_A(B1);
答案 1 :(得分:0)
这假定您事先知道所有子课程。如果没有,您可以使用一些虚拟Clone
函数创建原型注册系统。
要创建对象,我只需在结果上使用随机数生成器和switch
来确定要构造的类。为了处理回收内存,我返回std::unique_ptr
,因此客户端代码不必担心删除指针。
struct A {
//the random child class factory method
static std::unique_ptr<A> Getrandomobject();
//need a virtual destructor so that the child object is deleted properly
virtual ~A() =default;
private:
//random number generator
static std::mt19937 rng_;
//some state to check if the rng has been seeded
static bool inited_;
};
std::mt19937 A::rng_;
bool A::inited_ = false;
//our child classes
struct B1:A{};
struct B2:A{};
struct B3:A{};
struct B4:A{};
std::unique_ptr<A> A::Getrandomobject()
{
//seed rng if this is the first call
if (!inited_)
{
rng_.seed(std::random_device()());
inited_ = true;
}
std::uniform_int_distribution<std::mt19937::result_type> dist(0,3);
switch (dist(rng_))
{
case 0: return std::make_unique<B1>();
case 1: return std::make_unique<B2>();
case 2: return std::make_unique<B3>();
case 3: return std::make_unique<B4>();
default: return std::make_unique<B1>();
}
}
要检查这确实给了我们一个随机子类,我们可以使用以下测试代码(由于typeid
,结果将依赖于编译器):
int main() {
auto randomobject1 = A::Getrandomobject();
cout << typeid(*(randomobject1.get())).name();
return 0;
}
答案 2 :(得分:0)
#define MAX_CHILD_COUNT 3
A* A::GetRandomObject()
{
int _rand_index = rand()%MAX_CHILD_COUNT; // srand() before you call rand;
switch(_rand_index)
{
case 0:
return (new B1());
case 1:
return (new B2());
default:
return (new B3());
}
}
这个?