6

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++ 代码......我想征求任何建议,下一步该尝试什么。我的类不是派生类,例如是什么让我想知道。

4

2 回答 2

14

该错误意味着虚拟表尚未在最终二进制文件(可执行文件或库)中正确编译/链接。有两种常见情况会导致此错误:

  • 您没有链接包含虚拟表定义的目标文件 - 即您编译soapStub.cppsoapStub.o,但没有将该二进制文件添加到链接器命令行。
  • 编译器不会在任何地方生成虚拟表,因此即使您包含所有目标文件,也不包括虚拟表。

第二种情况对于没有经验的开发人员来说是最难识别的,并且可能是由在头文件中定义并包含虚函数的类引起的。如果所有虚函数都是内联定义的,编译器会在所有包含头文件的翻译单元中生成虚表,并将其标记为弱符号,以便链接器可以丢弃它们,但如果您稍后添加新的虚方法并如果您在标题中未定义它——或者如果您从其中一个虚拟函数中删除定义——那么编译器将不会在每个翻译单元中生成虚拟表,而只会在定义这些函数的那个​​中生成。

检查事项:

  • 您正在链接所有目标文件
  • 要么所有虚函数都在类定义中内联定义,要么你有一个定义虚函数的 .cpp 并且你正在链接它。
于 2011-01-04T12:25:41.093 回答
1

这就是大卫罗德里格斯所说的,我猜只是说得更简单......

我的接口类中有这种情况:

class IBase
{
    public:
    virtual void begin(unsigned long);
    virtual void end();
    virtual int available(void) = 0;
    virtual int peek(void) = 0;
    virtual int read(void) = 0;
    virtual void flush(void) = 0;
}

并将其更改为:

class IBase
{
    public:
    virtual void begin(unsigned long) = 0;
    virtual void end() = 0;
    virtual int available(void) = 0;
    virtual int peek(void) = 0;
    virtual int read(void) = 0;
    virtual void flush(void) = 0;
}

这成功了。

begin() 和 end() 是在不同文件的派生类中定义的,IBase 类(接口)仅在标头中声明并包含在少数地方。

仅当我将优化设置为无(-O0)时,才出现来自 OP 的错误,任何其他设置都不会导致错误(gcc 4.8)。

于 2015-03-31T03:16:31.457 回答