是否有任何不糟糕的方法来拥有多个类型的对象集合?我非常高兴能够从一个共同的基础派生出每种类型。我需要合理的语义,以便可以复制、分配集合等。
显然,我不能只使用基类的 vector 或列表。对象将被切片并且复制根本不起作用。使用 vector 或指针列表或智能指针是可行的,但您无法获得合理的复制语义。
要获得合理的复制语义,您需要使用 Boost 的 ptr_vector
之类的东西。但这需要一个痛苦且容易出错的基础设施。本质上,您不能仅仅从基类派生一个新类,因为如果它进入集合,它将无法正确复制。
这似乎是一件很常见的事情,而且我所知道的所有解决方案都非常糟糕。看起来 C++ 从根本上缺少一种创建与给定实例相同的对象的新实例的方法——即使该类型具有复制构造函数。制作clone
或duplicate
函数需要在每个派生类中仔细重载。如果您在创建从基类派生的新类(或从该基类派生的任何其他类)时未能做到这一点,那么您的集合就会崩溃。
真的没有更好的办法吗?
最佳答案
您可以使用std::vector<boost::any>
我认为完成大部分工作。
#include "boost/any.hpp"
#include <vector>
#include <iostream>
//Simple class so we can see what's going on
class MM {
public:
MM() { std::cout<<"Create @ "<<this<<std::endl; }
MM( const MM & o ) { std::cout<<"Copy "<<&o << " -> "<<this<<std::endl; }
~MM() { std::cout<<"Destroy @ "<<this<<std::endl; }
};
int main()
{
//Fill a vector with some stuff
std::vector<boost::any> v;
v.push_back(0);
v.push_back(0);
v.push_back(0);
v.push_back(0);
//Overwrite one entry with one of our objects.
v[0] = MM();
std::cout<<"Copying the vector"<<std::endl;
std::vector<boost::any> w;
w = v;
std::cout<<"Done"<<std::endl;
}
为此我得到输出:
Create @ 0xbffff6ae
Copy 0xbffff6ae -> 0x100154
Destroy @ 0xbffff6ae
Copying the vector
Copy 0x100154 -> 0x100194
Done
Destroy @ 0x100194
Destroy @ 0x100154
这就是我期望看到的。
编辑:
根据您的要求,能够将成员视为某种常见的基本类型,您将需要与 boost::any
非常相似的东西,幸运的是,这是一个相对简单的类。
template<typename BASE>
class any_with_base
{
// ... Members as for boost::any
class placeholder
{
virtual BASE * as_base() = 0;
//Other members as in boost::any::placeholder
};
template<typename ValueType>
class holder : public placeholder
{
virtual BASE * as_base() { return (BASE*)&held; }
//Other members as in boost::any::holder<T>
};
BASE* as_base() { return content?content->as_base():0; }
}
现在您应该能够执行以下操作:
vector< any_with_base<Base> > v;
v.push_back( DerivedA() );
v.push_back( DerivedB() );
v[0].as_base()->base_fn();
v[1].as_base()->base_fn();
any_cast<DerivedA>(v[0])->only_in_a();
我实际上不喜欢any_cast的语法,并会利用这个机会添加一个“as”成员函数..这样我就可以将最后一行写为:
v[0].as<DerivedA>()->only_in_a();
关于c++ - 超过一种类型的对象的集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10663106/