c ++对vtable的未定义引用

时间:2010-11-24 23:18:27

标签: c++ g++

我正在学习C ++。我正在尝试做一个练习,我用一个函数定义了几个纯虚拟类的实现。我无法链接使用这些实现的类。

==> BasicMath.h <==
#ifndef BASIC_MATH_H
#define BASIC_MATH_H

#include<string>
#include<vector>    

class BasicMath { };


#endif // BASIC_MATH_H

==> Operation.h <==

#ifndef OPERATION
#define OPERATION

#include<string>
#include<vector>    

class Operation {
 public:
  virtual void perform(std::vector<std::string> vec) = 0;
};


#endif // OPERATION

==> Sum.h <==
#ifndef SUM_H
#define SUM_H

#include "Operation.h"

class Sum: public Operation {
 public:
  void perform(std::vector<std::string> vec);
};

#endif // SUM_H

==> BasicMath.cpp <==
#ifndef BASIC_MATH_C
#define BASIC_MATH_C

#include <string>
#include <vector>
#include <iostream>
#include "BasicMath.h"
#include "Sum.h"

int main(int argc, char* argv[]) {
  Sum op;
}

#endif // BASIC_MATH_C

==> Sum.cpp <==
#ifndef SUM_C
#define SUM_C

#include <vector>
#include <string>
#include <iostream>
#include "Sum.h"

void Sum::perform(std::vector<std::string> vec) {
    using namespace std;
    int total = 0;
    cout << "Total: " << total << "\n";
};

#endif // SUM_C

汇编:

$ g++ -c Sum.cpp
$ g++ -o BasicMath BasicMath.cpp
/tmp/cc1VXjNl.o:BasicMath.cpp:(.text$_ZN3SumC1Ev[Sum::Sum()]+0x16): undefined reference to `vtable for Sum'
collect2: ld returned 1 exit status

我95%肯定我在这里至少做了一件愚蠢的事 - 但我的大脑拒绝告诉我什么。

我看到了this的问题,但未能解决我的问题。

7 个答案:

答案 0 :(得分:23)

我刚刚遇到同样的问题,但我的问题是我没有在我的.cpp文件中编写析构函数代码。

class.h:

class MyClass {
public:
    MyClass();
    virtual ~MyClass();
};

class.cpp:

MyClass::MyClass() {}

它只是给了我vtable错误信息,实现(空)析构函数解决了这个问题。

[编辑]因此,更正的类文件如下所示:

MyClass::MyClass() {}
MyClass::~MyClass() {}

答案 1 :(得分:16)

您没有在编译和链接行中包含Sum.o对象文件(第二次使用g ++)。

答案 2 :(得分:6)

有几个人已经指出了你所看到的问题的解决方案。

我会添加一些不同的东西。您只需要标题中的标题保护。您已将它们包含在源文件中,它们确实有意义。例如,我在sum.cpp中注释了你真正不需要(甚至不想要)的行:

//#ifndef SUM_C
//#define SUM_C
//
#include <vector>
#include <string>
#include <iostream>
#include "Sum.h"

void Sum::perform(std::vector<std::string> vec) {
    using namespace std;
    int total = 0;
    cout << "Total: " << total << "\n";
};

//#endif // SUM_C

只是FWIW而不是perform,我会使用operator()

class Operation {
 public:
  virtual void operator()(std::vector<std::string> vec) = 0;
};

和(显然)那也是Sum的重载。要使用它,而不是像:

Sum op;
op.perform();

您可以使用以下内容:

Sum op;
op();

当你将你的类与其他人(例如标准库中的那些人)结合起来调用像函数这样的操作,无论它们是真正的函数还是“函子”(像这样的类,重载{{1>从语法上讲,它们几乎可以像函数一样使用。)

答案 3 :(得分:3)

如果忘记纯虚函数的= 0

,也会发生错误

错误:

class Base {
    public:
        virtual void f();
};

class Derived : public Base {
    public:
        virtual void f() {}
};

int main() {
    Derived d;
    Base *b = &d;
}

没有错误:

class Base {
    public:
        virtual void f() = 0;
};

这是因为没有= 0,C ++不知道它是一个纯虚函数,将它视为一个声明,期待以后的定义。

g++ 5.2.1。

上进行测试

答案 4 :(得分:1)

你只是在没有Sum.cpp的情况下编译BasicMath.cpp - 你的链接器不知道Sum.cpp。您需要将它们一起编译,即一次性编译Sum.cpp BasicMath.cpp,或者您可以单独编译.cpp文件,然后通过使用两个.o文件调用g ++来创建可执行文件。

答案 5 :(得分:1)

当我在一个纯虚拟类中的某个函数的末尾意外忘记=0时,我通常会遇到此错误。

答案 6 :(得分:0)

我遇到了与您相同的问题,我通过在 CMakeLists.txt 中添加三行来解决了该问题,即:

set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)