c++ - 超过一种类型的对象的集合

标签 c++ object-slicing

是否有任何不糟糕的方法来拥有多个类型的对象集合?我非常高兴能够从一个共同的基础派生出每种类型。我需要合理的语义,以便可以复制、分配集合等。

显然,我不能只使用基类的 vector 或列表。对象将被切片并且复制根本不起作用。使用 vector 或指针列表或智能指针是可行的,但您无法获得合理的复制语义。

要获得合理的复制语义,您需要使用 Boost 的 ptr_vector 之类的东西。但这需要一个痛苦且容易出错的基础设施。本质上,您不能仅仅从基类派生一个新类,因为如果它进入集合,它将无法正确复制。

这似乎是一件很常见的事情,而且我所知道的所有解决方案都非常糟糕。看起来 C++ 从根本上缺少一种创建与给定实例相同的对象的新实例的方法——即使该类型具有复制构造函数。制作cloneduplicate函数需要在每个派生类中仔细重载。如果您在创建从基类派生的新类(或从该基类派生的任何其他类)时未能做到这一点,那么您的集合就会崩溃。

真的没有更好的办法吗?

最佳答案

您可以使用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/

相关文章:

c++ - Monodevelop C++ 调试问题

c++ - std::for_each 用法 -> 捕获变量

c++ - 避免切片异常类型 (C++)

C++ primer 5 Ed 全局对象

c++ - 无法增加 QToolButton 的大小(按钮样式设置为 Qt::ToolButtonTextBesideIcon)

c++ - 繁忙循环与 sleep (0)和暂停指令有什么不同?

c++ - 基类静态引用数据成员上 C++ 对象切片行为的奇怪情况

C++ 切片导致泄漏/未定义的行为/崩溃

c++ - 如何在不降级为基类的情况下制作*对象的 vector

C++调用基类方法切片对象