假设您在库中有一个基类:
class A {};
和派生类
class B: public A {};
class C: public A {};
现在B
和C
的实例存储在boost::shared_ptr<A>
的std :: vector中:
std::vector<boost::shared_ptr<A> > A_vec;
A_vec.push_back(boost::shared_ptr<B>(new B()));
A_vec.push_back(boost::shared_ptr<C>(new C()));
添加B
和C
的实例是由用户完成的,并且无法事先确定添加它们的顺序。
但是,在库内部,可能需要对B
和C
执行特定操作,因此指向基类的指针需要转换为B
并且C
。
我当然可以做&#34;试错&#34;转换,即尝试转换为B
和C
(以及基类的任何其他衍生物),直到我找到一个不会抛出的转换。然而,这种方法看起来非常粗糙且容易出错,而且我正在寻找一种更优雅(也更好的)方式。
我正在寻找一种也适用于C ++ 98的解决方案,但可能涉及提升功能。
有什么想法吗?
修改
哦,谢谢你到目前为止的所有答案!
我想提供有关用例的更多详细信息。所有这些都发生在参数优化的背景下。
用户通过以下方式定义优化问题:
然后,不同的优化算法会对问题定义起作用,包括它们的参数。
对于常见情况,有许多预定义的参数对象,但用户也可以通过从我的一个基类派生来创建自己的参数对象。因此,从库的角度来看,除了参数对象需要符合给定(基类)API之外,我不能对参数对象有太多假设。
问题定义是一个用户定义的C ++类,派生自带有std :: vector接口的基类。用户添加他的(预定义的或本地生成的)参数对象并重载适应度函数。
可能会发生对参数对象的访问
这很好用。
然而,可能会有特殊情况
在这些情况下,有一个简单的方法可以访问基类型集合中给定派生类型的所有参数对象。
我已经有了模板化&#34; conversion_iterator&#34;。它迭代基础对象的向量,并跳过那些不符合所需目标类型的对象。但是,这是基于&#34;试验和错误&#34;转换(即我检查转换的智能指针是否为NULL),我发现它非常不优雅且容易出错。
我希望有更好的解决方案。
注意:优化库的目标是用例,其中给定参数集的评估步骤可能持续任意长(通常为几秒,可能是几小时或更长)。因此,访问参数类型的速度不是很大的问题。但稳定性和可维护性是......
答案 0 :(得分:5)
没有比试图投射和看它是否成功更好的一般解决方案。你可以或者派生动态typeid
并依次将它与所有类型进行比较,但这实际上是相同的工作量。
更重要的是,你需要这样做暗示了设计问题:基类的整个目的是能够像对待父母一样对待孩子。在某些情况下,这是必要的,在这种情况下,您可以使用visitor来分发它们。
答案 1 :(得分:2)
如果可能,请向班级A
添加虚拟方法,以执行“B
和C
上的具体操作”。
如果这不可能或不合理,请使用dynamic_cast
的指针形式,因此不会涉及例外。
for (boost::shared_ptr<A> a : A_vec)
{
if (B* b = dynamic_cast<B*>(a.get()))
{
b->do_something();
}
else if (C* c = dynamic_cast<C*>(a.get()))
{
something_else(*c);
}
}
答案 2 :(得分:1)
添加B和C的实例是由用户完成的,并且无法预先确定添加它们的顺序。
好的,那么把它们放在两个不同的容器中?
std::vector<boost::shared_ptr<A> > A_vec;
std::vector<boost::shared_ptr<B> > B_vec;
std::vector<boost::shared_ptr<C> > C_vec;
void add(B * p)
{
B_vec.push_back(boost::shared_ptr<B>(p));
A_vec.push_back(b.back());
}
void add(C * p)
{
C_vec.push_back(boost::shared_ptr<C>(p));
A_vec.push_back(c.back());
}
然后你可以迭代Bs或Cs到你的心灵内容。
答案 3 :(得分:0)
我建议在基类中实现一个方法(例如TypeOf()),它将返回特定对象的类型。确保将该方法定义为虚拟和抽象,以便强制您在派生类型中实现。至于类型本身,您可以为每种类型(例如类)定义枚举。
enum class ClassType { ClassA, ClassB, ClassC };
答案 4 :(得分:0)
您可能会对此答案感兴趣: Generating an interface without virtual functions?
这显示了两种方法