Реализация конструктора копирования
У меня есть следующее определение класса, и ему нужен конструктор копирования, поэтому создаются глубокие копии для копирования необработанных указателей. Кто-нибудь может посоветовать, как лучше всего это сделать?
Использование 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 ¤tnode);
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. Так что я не могу просто назвать новые на этих указателях.
Не уверен, что я просто буквально воссоздаю все эти объекты?
Пример:
document = impl->createDocument(0, "mydoc", 0);
Кто ушел в гнев downvote и не дали причину???
5 ответов
Эта страница, безусловно, может помочь:
http://icu-project.org/docs/papers/cpp_report/the_anatomy_of_the_assignment_operator.html
Обратите внимание, что они отличаются от написания конструктора копирования и оператора присваивания, но этот момент также обсуждается в статье.
Написание конструктора копирования всегда связано с выполнением "правильных действий" для каждой переменной-члена. Не видя документации по API для вашего DOMImplementation
и т. д., трудно сказать, что было бы "Правильным" здесь. Возможно, для них есть конструктор копирования или функция для создания глубокой копии. Возможно, вам не нужна глубокая копия, семантически (например, для DOMImplementation
).
Итог, трудно сказать, не видя документов по API, которые у вас наверняка есть...
Изменить: Таким образом, вы используете Xerces-C. Вы не говорили нам это раньше...
Редактировать 2: Давайте посмотрим, тогда...
API Xerces-C действительно не предоставляет каких-либо "простых" способов копирования объекта документа, как я вижу. AFAICT, вам придется создать совершенно новый документ (impl->createDocument()
), а затем скопируйте любые атрибуты и дочерние узлы вручную.
Это так неловко, я бы поднял вопрос "почему я хочу скопировать мой XMLDocument
объект вообще? Имеет ли это смысл на семантическом уровне?". (Личный опыт: если дела идут плохо при работе с хорошо используемым API, есть вероятность, что вы делаете что-то не так, иначе был бы легкий путь. XML не моя сильная черта, так что я вне моей глубины здесь.)
Если глубокое копирование, которое вы хотите, возможно с библиотекой, которую вы используете, то способ сделать это - убедиться, что каждый член данных вашего класса принадлежит XMLDocument
умеет копировать себя (используя собственный конструктор копирования). И так далее рекурсивно для каждого типа элемента данных. На практике это означает определение копируемых типов оболочек с нуля.
Постарайтесь точно определить, что принадлежит (подлежит копированию), а что нет (существует в другом месте и только что на него ссылаются).
Основная причина такого иерархического переноса заключается в том, что вы хотите, чтобы автоматическое уничтожение C++ срабатывало при сбое копирования части. Но это также значительно упрощает вещи. И когда вы переходите к самым низким уровням составных частей, вы можете получить лучший совет по копированию такой маленькой части.
Ура & hth.,
Devsolar прав насчет конструкторов копирования. Прислушайтесь к его совету.
Кроме того, вы действительно не должны копировать структуры DOM. Стандартной процедурой, когда я работаю с XML, является написание обработчика, который получает данные из DOM/SAX и создает собственный объект на основе этой структуры. Как только вы закончите чтение всех элементов DOM/SAX, вы должны сконструировать их в памяти:
- Структура данных, которая содержит все необходимые данные из XML.
- Объект, построенный из XML, но отделенный от XML. Вы используете этот объект в вашем приложении. Скорее всего, вы будете сериализовать этот объект в XML в будущем.
Таким образом, вам не нужно копировать DOM. Вместо этого вы создаете собственные объекты для представления данных. Помните, что вы хотите отделить свое приложение от XML. Что если в будущем вы решите использовать двоичную сериализацию?
Я бы рекомендовал немного переосмыслить правила владения. Если вы хотите сделать глубокое копирование, скорее всего, вы пытаетесь обойти то, какая переменная владеет памятью других переменных. В вашем случае кажется, что вы заботитесь о каждом экземпляре XMLDocument, владеющем переменными v_nodes и DOM.
Еще один способ решить основные проблемы - заключить переменные вашего экземпляра в умные указатели.
Таким образом, каждый раз, когда вы копируете конструкцию XMLDocument, вы просто увеличиваете количество ссылок для каждого из иваров. Каждый раз, когда вызывается dtor для экземпляра XMLDocument, количество ссылок уменьшается. По сути, вы отделяете время жизни каждого экземпляра XMLDocument от его ivars. Вместо этого, он принадлежит подсчету ссылок.
Я не эксперт по xerces, но стоит проверить различные реализации smart ptr, например, библиотеку boost.