我正在重写一个项目,以便它使用getter和setter来引用TiXmlElement *的
但是,我很快遇到了似乎与 Debug模式有关的问题:

从我类(class)的标题摘录:

TiXmlElement *_rootElement;
TiXmlElement *_dialogsElement;
TiXmlElement *_dialogElement;
TiXmlDocument _document;
void setDocument (TiXmlDocument doc) { this->_document = doc; }
void setRootElement (TiXmlElement * element) { this->_rootElement = element; }
void setDialogsElement (TiXmlElement * element) { this->_dialogsElement = element; }

TiXmlDocument getDocument () { return this->_document; }
TiXmlElement* getRootElement () { return this->_rootElement; }
TiXmlElement* getDialogsElement () { return this->_dialogsElement; }

摘自类构造函数:
DCXML::DCXML(const char *dialogMark,const char *dialogName,TiXmlDocument doc) {
...
this->setDocument(doc);
this->setRootElement(this->getDocument().FirstChildElement("dcxml"));
this->setDialogsElement(this->getRootElement()->FirstChildElement("dialogs"));

实例化该类的节选:
TiXmlDocument doc(input.gettok(2,"\"").to_chr());
bool dcxmlFile = doc.LoadFile();
...
DCXML *dcxml = new DCXML(input.gettok(2).to_chr(),input.gettok(3).to_chr(),doc);

现在开始怪异的部分。这工作直到
this->setDialogsElement(this->getRootElement()->FirstChildElement("dialogs"));

在构造函数中。

->在 Debug模式下,VS2008中的FirstChildElement(“dialogs”)在VS2008中引发“CXX0039:错误:符号不明确”错误。

奇怪的是,IntelliSense会选择FirstChildElement方法,并且编译器不会引发任何错误。

甚至更奇怪的是,在 Release模式下,它只是默默地无法获取dialogs元素。

我做错了什么?或者,如果您已经成功地为TiXmlElement *实现了getter setter包装器,请让我知道我该如何做!

要完整引用,以下是XML文件的摘录:
<?xml version="1.0" encoding="utf-8"?>
<dcxml>
    <dialogs>
        <dialog
            name="mediaplayer"
            center=""
            w="300"
            h="400"
            caption="Mamp 4.0 BETA"
            border="btmnzy">
        </dialog>
    </dialogs>
</dcxml>

反馈将不胜感激,因为我处于死胡同:)

最佳答案

确保

TiXmlDocument getDocument () { return this->_document; }

不会深度复制其包含的TiXmlElement。否则,您将返回一个临时变量,请在构造函数中使用该变量设置根节点,然后将其销毁。我没有看过它的API,但要注意这些陷阱。

产生歧义的原因是:
FirstChildElement的三个重载采用一个参数:
const TiXmlElement *    FirstChildElement (const char *value) const // :1
const TiXmlElement *    FirstChildElement (const std::string &_value) const // :2
TiXmlElement       *    FirstChildElement (const std::string &_value) // :3

您可以通过TiXmlElement&(使用TiXmlElement*指针)访问TiXmlElement。但是采用const char*的版本具有隐式对象参数TiXmlElement const&。也就是说,需要进行资格转换才能使 call 正常进行。对于采用std::string const&的其他版本,也需要进行转换:
<implied obj param> <implicit obj param>    <arg1>         <param1>
TiXmlElement&        TiXmlElement const&    char const*    char const*         // :1
TiXmlElement&        TiXmlElement const&    char const*    std::string const&  // :2
TiXmlElement&        TiXmlElement&          char const*    std::string const&  // :3

第一个和第三个过载之间存在歧义。一个简单的解决方法是
this->setDialogsElement(
    this->getRootElement()->FirstChildElement(std::string("dialogs")));

相反,它将调用最新版本。另一个修复方法是const_cast:
this->setDialogsElement(
    const_cast<TiXmlElement const*>(this->getRootElement())->
        FirstChildElement("dialogs"));

它将称为第一个版本。至于为什么它只在DEBUG中发生...我记得TiXML可以选择禁用STL。也许在 Release模式下您禁用了它(并因此禁用了std::string的重载),但是在 Debug模式下您忘记了?

10-07 18:53