我正在学习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的问题,但未能解决我的问题。
答案 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)