对 vtable 的未定义引用 - 虚拟成员,由 gsoap 生成的类
gsoap 及其工具 wsdl2h 和soapcpp2 为我提供了一个soapStub.h 文件,其中包含以下内容:
class SOAP_CMAC ns2__SOAPKunden
{
public:
std::string *adresszusatz;
// ...
public:
virtual int soap_type() const { return 7; }
// ...
ns2__SOAPKunden() : adresszusatz(NULL), x(NULL) { } // left out all member init.
virtual ~ns2__SOAPKunden() { }
};
我从一个小应用程序开始,使用该类用来自informix DB 的数据填充对象。
但是为了成功编译,我必须放弃所有虚拟的东西 - 我发现很多关于这个错误和在子类中使用虚拟成员的帖子 - 否则我承认
main.o: In function `ns2__SOAPKunden::ns2__SOAPKunden()':
main.cpp:(.text._ZN15ns2__SOAPKundenC1Ev[ns2__SOAPKunden::ns2__SOAPKunden()]+0xf): undefined reference to `vtable for ns2__SOAPKunden'
main.o: In function `ns2__SOAPKunden::~ns2__SOAPKunden()':
main.cpp:(.text._ZN15ns2__SOAPKundenD1Ev[ns2__SOAPKunden::~ns2__SOAPKunden()]+0x13): undefined reference to `vtable for ns2__SOAPKunden'
collect2: ld returned 1 exit status
经过多年的脚本编写,我很难理解 C++ 代码...我想寻求任何建议,下一步该尝试什么。我的类不是派生类,这让我感到好奇。
gsoap with its tools wsdl2h and soapcpp2 provided me with a soapStub.h file containing the following:
class SOAP_CMAC ns2__SOAPKunden
{
public:
std::string *adresszusatz;
// ...
public:
virtual int soap_type() const { return 7; }
// ...
ns2__SOAPKunden() : adresszusatz(NULL), x(NULL) { } // left out all member init.
virtual ~ns2__SOAPKunden() { }
};
I start with a small app using the class to populate objects with data from informix DB.
But to compile successfully i have to leave away all the virtual stuff - i found many postings about this error and use of virtual members in subclasses - otherwise i get
main.o: In function `ns2__SOAPKunden::ns2__SOAPKunden()':
main.cpp:(.text._ZN15ns2__SOAPKundenC1Ev[ns2__SOAPKunden::ns2__SOAPKunden()]+0xf): undefined reference to `vtable for ns2__SOAPKunden'
main.o: In function `ns2__SOAPKunden::~ns2__SOAPKunden()':
main.cpp:(.text._ZN15ns2__SOAPKundenD1Ev[ns2__SOAPKunden::~ns2__SOAPKunden()]+0x13): undefined reference to `vtable for ns2__SOAPKunden'
collect2: ld returned 1 exit status
I admit after years of scripting only it's very hard for me to make sense of C++ code... I want to ask for any advice what to try next. My class is no derived class, is for example what makes me wonder.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
该错误意味着虚拟表尚未在最终二进制文件(可执行文件或库)中正确编译/链接。有两种常见情况会导致此错误:
soapStub.cpp
编译为soapStub.o
,但没有将该二进制文件添加到链接器命令行中。对于没有经验的开发人员来说,第二种情况最难识别,可能是由标头中定义的包含虚函数的类引起的。如果所有的虚函数都是内联定义的,编译器会在包含头的所有翻译单元中生成虚表,并将其标记为弱符号,以便链接器可以丢弃它们,但如果稍后添加新的虚方法并且如果您在标头中保留其未定义,或者如果从其中一个虚拟函数中删除定义,那么编译器将不会在每个翻译单元中生成虚拟表,而只会在定义这些函数的翻译单元中生成虚拟表。
要检查的事情:
The error means that the virtual table has not been correctly compiled/linked in the final binary (executable or library). There are two common circumstances that lead to this error:
soapStub.cpp
intosoapStub.o
, but did not add that binary to the linker command line.The second case is the hardest to identify for non-experienced developers, and can be caused by a class that is defined in the header and contains virtual functions. If all the virtual functions are defined inlined, the compiler will generate the virtual table in all translation units that include the header, and mark it as a weak symbol so that the linker can discard them, but if you later add a new virtual method and you leave it undefined in the header --or if you remove the definition from one of the virtual functions--, then the compiler will not generate the virtual table in each translation unit, but only in the one that defines those functions.
Things to check:
这就是大卫·罗德里格斯所说的,我想只是说得更简单......
我在我的接口类中遇到了这种情况:
并将其更改为:
这起到了作用。
begin() 和 end() 在不同文件的派生类中定义,IBase 类(接口)仅在标头中声明并包含在少数地方。
仅当我将优化设置为无(-O0)时,OP 错误才会出现,任何其他设置都不会导致错误(gcc 4.8)。
This is what David Rodriguez said, just stated simpler I guess...
I had this situation in my interface class:
and changed it to this:
which did the trick.
begin() and end() were defined in derived class in a different file, IBase class (interface) was only declared in header and included in few places.
Error from OP only appeared when I set optimizations to none (-O0), any other setting resulted in no error (gcc 4.8).