嵌套类 C++静态内部方法(Xml 解析并尝试用值填充向量)
这就是我正在努力实现的目标。我正在尝试使用 sax 解析器来解析一些 XML。看起来我需要将它们的所有方法称为静态方法。因此,如果我想从 startElement 传回一个值,它是 static void startElement。这让我看到了我的示例代码。我一直在研究如何从静态成员函数更新嵌套类中的值。
我已经研究了一些东西,例如定义 OuterClass * oc;然后尝试引用 oc->allRecords,但由于它是内部的静态方法,因此失败。我确信我在架构上做错了一些事情,所以任何关于正确方法的反馈都会有很大的帮助。谢谢。
class Attribute {
string AttributeName;
string AttributeValue;
};
typedef shared_ptr<Attribute> AttributePtr;
class AttributeSet {
vector<AttributePtr> Attributes;
};
typedef shared_ptr<AttributeSet> AttributeSetPtr;
class OuterClass {
public :
vector<AttributeSetPtr> allRecords;
class InnerClass {
public:
static mymethod1() {
// I need to be able to set attributes here :
// This would be the characters method for sax parsing
// What is the right way to Attributes.push_back(new Attribute(Name,Value));
}
static mymethod2() {
// I also need to be able to add Records here :
// This would be the endElement for sax parsing
// What is the right way to allRecords.push_back(AttributeSet);
}
};
// EDIT: CALLING CODE GOES HERE (WAS EDITED - SEE BELOW)
};
// ADDING INFORMATION REGARDING HOW METHOD 1 & 2 are called
xmlSAXHandler saxHandler;
memset(&saxHandler, 0, sizeof(saxHandler));
saxHandler.initialized = XML_SAX2_MAGIC;
...
saxHandler.endElementsNs = &InnerClass::method2;
saxHandler.characters = &InnerClass::method1;
...
InnerClass innerXmlParsingClass
xmlSaxUserParseMemory( &saxHandler, &innerXmlParsingClass, xmlString, xmlString.length());
So this is what I am trying to accomplish. I am trying to use a sax parser to parse some XML. it looks like I need to call all their methods as statics. So if I want to pass a value back from say startElement it is static void startElement. Which brings me to my example code. I have been pulling my hair on how to update a value in a Nesting class from a static member function.
I have looked at several things such as defining OuterClass * oc; then trying to reference oc->allRecords, but since it is a static method inside, it fails. I am sure I am doing something wrong architecturally, so any feedback on what would be the right way to do this would be a great help. Thanks.
class Attribute {
string AttributeName;
string AttributeValue;
};
typedef shared_ptr<Attribute> AttributePtr;
class AttributeSet {
vector<AttributePtr> Attributes;
};
typedef shared_ptr<AttributeSet> AttributeSetPtr;
class OuterClass {
public :
vector<AttributeSetPtr> allRecords;
class InnerClass {
public:
static mymethod1() {
// I need to be able to set attributes here :
// This would be the characters method for sax parsing
// What is the right way to Attributes.push_back(new Attribute(Name,Value));
}
static mymethod2() {
// I also need to be able to add Records here :
// This would be the endElement for sax parsing
// What is the right way to allRecords.push_back(AttributeSet);
}
};
// EDIT: CALLING CODE GOES HERE (WAS EDITED - SEE BELOW)
};
// ADDING INFORMATION REGARDING HOW METHOD 1 & 2 are called
xmlSAXHandler saxHandler;
memset(&saxHandler, 0, sizeof(saxHandler));
saxHandler.initialized = XML_SAX2_MAGIC;
...
saxHandler.endElementsNs = &InnerClass::method2;
saxHandler.characters = &InnerClass::method1;
...
InnerClass innerXmlParsingClass
xmlSaxUserParseMemory( &saxHandler, &innerXmlParsingClass, xmlString, xmlString.length());
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
你的错误是使用内部类(你来自Java吗?)。
我不知道你认为你通过内部类能实现什么目标,但它不会起作用。不要在 C++ 中使用内部类,除非您确实知道它的用途(对于内部类,外部类的受保护成员和私有成员被视为公共成员)。
现在,作为您问题的解决方案,我想这取决于您正在使用的实现(我曾经使用过 Apache 的 Xerces SAX,但我知道 Microsoft 提供了自己的 SAX 实现,并且应该有很多其他替代方案,所以。 ..)
编辑
评论后,我发现以下教程:
http://www.jamesh.id.au/articles/libxml-sax/libxml-sax.html
我必须说,从Java到C++,并使用C API,你有一种勇气...
:-D
如果您对函数指针和 C 语言不太熟悉,那么使用 libxml2 将是一个挑战。确保最终您会理解这些概念...请注意,C 有一种方法来处理 C++、Java 或 C# 开发人员与
this
关联的数据。 C 方式是将指向数据(用户数据)的指针传递给函数,当调用回调时,它会传回该指针,类型为void *
。然后,您必须将其转换回正确的类型,然后voilà,您就恢复了this
。:-)
无论如何,阅读文档,我发现当您解析文件时,您将调用以下 C 函数:
user_data
部分是您感兴趣的部分,因为它使您能够拥有语境。因此,将此函数包装在 C++ 类中,您可能会得到如下内容:
我没有对此进行测试,而且我从未使用过 libxml2,但我想代码一定是好的,这应该足以让您继续自己继续:只需添加您想要支持的方法,使用相关的初始化 sax 处理程序函数指针,这样你的类就完成了。
MySaxBase::startDocument
和MySaxBase::endDocument
方法是虚拟的,只是为了让您从 MySaxBase 派生,然后重写这些方法。编辑 2
我将在这里重现 Steve Jessop 的精彩评论:
在此之后,并在阅读 Johannes Schaub - litb(还有谁?)< a href="https://stackoverflow.com/questions/592160/static-vs-extern-c/592205#592205">static vs extern "C"/"C++" ,我修改了代码以使
do_startDocument
和do_endDocument
真正的 C 函数(即包装在 extern“C”块中)。这通常并不重要(我从未遇到过此类问题),但是,安全总比后悔好。Your mistake is using an inner class (are you coming from Java?).
I don't know what you believe you are are achieving with an inner class, but it won't work. Don't use inner classes in C++ unless you really know what it does (for inner classes, protected and private members of the outer classes are seen as if they were public).
Now, as the solution to your problem, I guess it depends on the implementation you're using (I used once Apache's Xerces SAX, but I know Microsoft offers its own SAX implementation, and that there should be a lot other alternatives, so...)
Edit
After the comment, I found the following tutorial:
http://www.jamesh.id.au/articles/libxml-sax/libxml-sax.html
I must say that, coming from Java to C++, and using a C API, you have a kind of courage...
:-D
If you are not familiar enough with function pointers, and C in general, using libxml2 will be a challenge. Be sure that in the end, you will understand those notions... Note that C have a way to handle the data that C++, Java or C# developers associate to
this
. The C way is to pass a pointer to your data (the user data) to a function, and when the callback is called, it passes back this pointer, typed as avoid *
. You must then cast it back to its right type, and voilà, you have yourthis
back.:-)
Anyway, reading the doc, I see that when you parse the file, you'll call the following C function:
the
user_data
part is the one that interest you because it enables you to have a context. So, wrapping this function in a C++ class, you could have something like:.
I did not test this, and I never used libxml2, but I guess the code must be Ok, and this should be enough for you to continue on your own: Just add the methods you want to support, initialize the sax handler with the relevant function pointers, and you'll have your class complete.
The
MySaxBase::startDocument
andMySaxBase::endDocument
methods are virtual just for you to derive from MySaxBase and then override those methods.Edit 2
I'll reproduce here Steve Jessop's excellent comment:
Following this, and after reading Johannes Schaub - litb (who else?) no less excellent answer at static vs extern "C"/"C++" , I modified the code to make
do_startDocument
anddo_endDocument
real C functions (i.e. wrapped in an extern "C" block). This usually is not important (I never encountered this kind of problem), but, better safe than sorry.您的基本问题是
static
方法不是每个实例的,因此没有this
指针。您以某种方式需要将OuterClass*
传递给mymethod1
和mymethod2
。如果您向我们展示如何调用
mymethod1
和mymethod2
,我们可以为您提供进一步帮助。如果您只是在有
OuterClass
对象的地方调用它,那么您的解决方案很简单:Your basic problem is that
static
methods are not per-instance, so there is nothis
pointer. You somehow need to get aOuterClass*
passed tomymethod1
andmymethod2
.If you show us how
mymethod1
andmymethod2
are called, we can help you further.If it's simply called by you someplace where you have a
OuterClass
object, then your solution is simple:既然您在这里更新了您的问题,那么您应该如何执行此操作:
Since you updated your question here is how you should do this: