实现复制构造函数

时间:2010-11-03 15:03:21

标签: c++ copy-constructor

我有以下类定义,它需要一个复制构造函数,因此可以复制原始指针。有人可以建议如何做到最好吗?

xerces-c++用于XML

class XMLDocument 
 {
 private:
  typedef std::vector<XML::XMLNode> v_nodes;
 public:
  XMLDocument::XMLDocument();
  XMLDocument::XMLDocument(const XMLDocument& copy); 
  XMLDocument::~XMLDocument();

  XMLDocument& operator=(XMLDocument const& rhs);

  void CreateDocument(const std::string& docname);
  void AddChildNode(XMLNode& node);
  void RemoveNode(XMLNode& node);
  void AddNodeValue(XMLNode& node, const std::string& value);
  void AddNodeValue(XMLNode& node, int value);
  void AddNodeValue(XMLNode& node, double value);
  void AddNodeValue(XMLNode& node, float value);
  std::string GetXMLAttributes();
  std::string GetXMLAttribute(const std::string& attrib);
  std::string GetXMLNodeText(XML::XMLNode& node);
  std::string DumpToString();
  XMLNode GetXPathNode(const std::string xpathXpression);
  XMLNode GetNode(const XMLNode &currentnode);

  typedef v_nodes::iterator nodes_iterator;
  nodes_iterator begin()
  {
   nodes_iterator iter;
   iter = xmlnodes.begin();

   return iter;
  }
  nodes_iterator end()
  {
   nodes_iterator iter;
   iter = xmlnodes.end();

   return iter; 
  }


 private:
  v_nodes xmlnodes;

  bool InitializeXML();
  DOMImplementation* impl; //Abstract
  DOMDocument* document; //Abstract
  DOMElement* rootelement; //Abstract

 };

DOMDocument 创建时调用函数所以是DOMElement。所以我不能只是在这些指针上调用new。

不确定我是否只是重新创建所有这些对象?

示例:

document = impl->createDocument(0, "mydoc", 0);

谁进行了一次沮丧的愤怒并没有给出理由?

5 个答案:

答案 0 :(得分:2)

编写复制构造函数总是为每个成员变量做“正确的事”。如果没有看到DOMImplementation等的API文档,很难说“正确的事情”会是什么。也许它们有一个复制构造函数,或者是一个进行深层复制的函数。也许你不是需要一个深层拷贝,在语义上(例如DOMImplementation)。

最重要的是,如果没有看到API文档就很难说你肯定已经躺在那里了......

编辑:所以你使用的是Xerces-C。你之前没有告诉我们......

编辑2:让我们看看,然后......

Xerces-C API确实提供任何“简单”的复制文档对象的方法,从我所看到的。 AFAICT,您必须创建一个全新的文档(impl->createDocument()),然后手动复制任何属性和子节点。

这是如此尴尬,我会提出一个问题“为什么我是否想要复制我的XMLDocument对象?无论如何它在语义层面上是否有意义?”。 (个人经验:如果在使用一个使用良好的API时情况变得很难看,你可能会做错事,因为否则会有一个简单的方法.XML不是我的强势,所以我不在我的深度此处。)

答案 1 :(得分:2)

此页面可能会有所帮助:
http://icu-project.org/docs/papers/cpp_report/the_anatomy_of_the_assignment_operator.html

请注意,编写复制构造函数和赋值运算符之间存在差异,但本文也讨论了这一点。

答案 2 :(得分:1)

Devsolar对于复制构造函数是正确的。听取他的意见。

此外,你真的不应该复制DOM结构。使用XML时的标准过程是编写一个从DOM / SAX获取数据的处理程序,并根据该结构构建一个本机对象。一旦你完成了你应该在内存中构建的所有DOM / SAX元素:

  1. 一种数据结构,用于保存XML所需的所有数据。
  2. 从XML构建但与XML分离的对象。您在应用程序中使用此对象。很可能您将来会将此对象序列化为xml
  3. 这样您就不需要复制DOM了。您可以构建本机对象来表示数据。请记住,您希望将应用程序与XML分离。如果您将来决定使用二进制序列化怎么办?

答案 3 :(得分:1)

如果您正在使用的库可以进行深层复制,那么实现它的方法是确保您的班级XMLDocument中的每个拥有的数据成员知道如何复制自己(使用自己的复制构造函数)。等等每个数据成员的类型递归。实际上,这意味着从头开始定义可复制的包装类型。

注意确切地定义所拥有的(被复制的)和不属于的(在其他地方存在并且仅被引用)。

这种分层包装的主要原因是,当某个部件的复制失败时,您希望C ++的自动销毁。但它也大大简化了事情。当你得到最低级别的组成部分时,你可能会得到更好的建议来复制这么小的部分。

干杯&amp;第h。,

答案 4 :(得分:0)

我建议稍微重新考虑所有权规则。如果你想做一个深层复制,你可能正在尝试解决变量拥有其他变量的内存。在您的情况下,您似乎关心拥有v_nodes和DOM相关变量的XMLDocument的每个实例。

解决潜在问题的另一种方法是将实例变量包装在智能指针中。

通过这种方式,每次复制构造XMLDocument时,您只是在每个ivar上碰撞引用计数。每次调用XMLDocument实例的dtor时,ref计数都会减少。实质上,您将每个XMLDocument实例的生命周期与其ivars分离。相反,它是拥有它的引用计数。

我不是xerces的专家,但值得查看各种智能ptr实现,例如:升级库。