【问题标题】:Clone allocators, and polymorphism in boost::ptr_containerboost::ptr_container 中的克隆分配器和多态性
【发布时间】:2012-05-07 00:43:01
【问题描述】:

对于我当前的项目,我使用boost::ptr_vector 以多态方式保存Objects,并且一切正常,直到我的一个构建VS2010 抛出它无法克隆object,所以我去查找克隆,并按照boost 的要求实现了new_clone() 方法,并按照c++ FAQ 使其成为pure virtual,但现在VS2010 向我扔了这个shanagin,说它不能在抽象类上使用克隆。

1>c:\program files\boost\boost_1_49_0\boost\ptr_container\clone_allocator.hpp(34): error C2259: 'Object' : cannot instantiate abstract class
1>          due to following members:
1>          'Object *Object::new_clone(void) const' : is abstract
1>          c:\...\Object.h(36) : see declaration of 'Object::new_clone'
1>          c:\program files\boost\boost_1_49_0\boost\ptr_container\clone_allocator.hpp(68) : see reference to function template instantiation 'T *boost::new_clone<U>(const T &)' being compiled
1>          with
1>          [
1>              T=Object,
1>              U=Object
1>          ]
1>          c:\program files\boost\boost_1_49_0\boost\ptr_container\detail\reversible_ptr_container.hpp(110) : see reference to function template instantiation 'U *boost::heap_clone_allocator::allocate_clone<Object>(const U &)' being compiled
1>          with
1>          [
1>              U=Object
1>          ]
1>          c:\program files\boost\boost_1_49_0\boost\ptr_container\detail\reversible_ptr_container.hpp(99) : while compiling class template member function 'Object *boost::ptr_container_detail::reversible_ptr_container<Config,CloneAllocator>::null_clone_allocator<allow_null_values>::allocate_clone(const Object *)'
1>          with
1>          [
1>              Config=boost::ptr_container_detail::sequence_config<Object,std::vector<void *,std::allocator<void *>>>,
1>              CloneAllocator=boost::heap_clone_allocator,
1>              allow_null_values=false
1>          ]
1>          c:\program files\boost\boost_1_49_0\boost\ptr_container\detail\reversible_ptr_container.hpp(276) : see reference to class template instantiation 'boost::ptr_container_detail::reversible_ptr_container<Config,CloneAllocator>::null_clone_allocator<allow_null_values>' being compiled
1>          with
1>          [
1>              Config=boost::ptr_container_detail::sequence_config<Object,std::vector<void *,std::allocator<void *>>>,
1>              CloneAllocator=boost::heap_clone_allocator,
1>              allow_null_values=false
1>          ]
1>          c:\program files\boost\boost_1_49_0\boost\ptr_container\detail\reversible_ptr_container.hpp(275) : while compiling class template member function 'void boost::ptr_container_detail::reversible_ptr_container<Config,CloneAllocator>::null_policy_deallocate_clone(const Object *)'
1>          with
1>          [
1>              Config=boost::ptr_container_detail::sequence_config<Object,std::vector<void *,std::allocator<void *>>>,
1>              CloneAllocator=boost::heap_clone_allocator
1>          ]
1>          c:\program files\boost\boost_1_49_0\boost\ptr_container\ptr_sequence_adapter.hpp(132) : see reference to class template instantiation 'boost::ptr_container_detail::reversible_ptr_container<Config,CloneAllocator>' being compiled
1>          with
1>          [
1>              Config=boost::ptr_container_detail::sequence_config<Object,std::vector<void *,std::allocator<void *>>>,
1>              CloneAllocator=boost::heap_clone_allocator
1>          ]
1>          c:\program files\boost\boost_1_49_0\boost\ptr_container\ptr_vector.hpp(35) : see reference to class template instantiation 'boost::ptr_sequence_adapter<T,VoidPtrSeq,CloneAllocator>' being compiled
1>          with
1>          [
1>              T=Object,
1>              VoidPtrSeq=std::vector<void *,std::allocator<void *>>,
1>              CloneAllocator=boost::heap_clone_allocator
1>          ]
1>          c:\general\dev\senior\tankbattle3d\tankbattle3d\tankbattle3d\room.h(28) : see reference to class template instantiation 'boost::ptr_vector<T>' being compiled
1>          with
1>          [
1>              T=Object
1>          ]

这是否意味着为了让 boost 能够克隆东西,我必须扔掉抽象基类?


注意事项:

  • 在任何时候都不应在程序中存在抽象基类的对象,但几乎所有东西都会被这样对待。
  • 当我将克隆方法设置为非虚拟方法并为其提供实际返回某些内容的方法(提供构造函数/复制构造函数,这意味着它们可能存在,这与设计相违背)时,编译器会抛出所有驱动的类需要一个默认构造函数。没有它们是设计使然。

编辑:我没有实现delete_clone()(不知道这是明确要求的,我认为析构函数会很好)

class Object{
public :
    ObjectType  superType;
    bool toBeRemoved;
    virtual void performAction(int action, Object& source){}
    virtual void updateObject(float duration){}
    virtual ~Object(){}
    virtual Object * new_clone(void)const = 0;      // Object.h[36]
    bool operator==(const Object& _other)const;
    bool operator!=(const Object& _other)const;
};

【问题讨论】:

  • 你能告诉我们Object的定义吗?特别是Object.h(36)附近的区域?另外,您能告诉我们您对new_clonedelete_clone 函数的定义吗?

标签: c++ visual-studio-2010 boost-ptr-container


【解决方案1】:

你想要的是一个独立的(非成员)new_clone() 函数,编译器会优先选择它而不是 Boost 的 clone_allocator.hpp 中的函数:

class Object{
public :
    ObjectType  superType;
    bool toBeRemoved;
    virtual void performAction(int action, Object& source){}
    virtual void updateObject(float duration){}
    virtual ~Object(){}
    bool operator==(const Object& _other)const;
    bool operator!=(const Object& _other)const;

private:
    virtual Object * do_clone() const = 0;
};

// in the same namespace as `class Object`:
//  so it will get picked up instead of Boost's default 
//  implementation

inline
Object* new_clone( const Object& o)
{
    return o.do_clone();
}

【讨论】:

  • 我是否也为派生类做类似的事情(尽管它们的克隆方法实际上有实现),或者这只是为了abstract base class
  • @gardian06:这仅适用于您提供给ptr_vector 的类型。如果您需要执行特定于派生类型的工作,则假定您将拥有一些虚拟(可能是纯)成员函数来完成实际工作。它只是一个简单的钩子,因此您不必创建具有特定名称的成员函数。这样,如果您已经因为其他原因进行了克隆,全局挂钩将让 ptr_vector 使用它。
  • 只是补充一下 Nicol 所说的:do_clone() 虚函数将需要在每个派生类中实现,以完成克隆实例的实际工作。这个非成员函数“遵从”虚函数。
  • 好吧,虽然它会在之前声明的对象中导致 LNK1169 和 2005
  • 啊 - 对不起。如果您将实现放在头文件中,我就省略了应该存在的inline(这可能是因为它是一个如此简单的函数)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-17
  • 1970-01-01
  • 2020-08-08
  • 1970-01-01
  • 1970-01-01
  • 2015-12-15
  • 2013-05-29
相关资源
最近更新 更多