【发布时间】:2016-10-28 02:00:14
【问题描述】:
我已经开始编写一个模拟 shell 程序,但很快就遇到了问题。 编译我的项目时,我得到了一个未定义的对 `vtable for Cmd' 的引用
Shell.h
#ifndef SHELL_H
#define SHELL_H
#include <iostream>
#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <stdlib.h>
#include <cstring>
using namespace std;
class Shell
{
protected:
char* cmd;
public:
Shell(): cmd(NULL){};
Shell(char* userInput): cmd(userInput){};
virtual bool execute() = 0;
};
#endif
Cmd.h
#ifndef CMD_H
#define CMD_H
#include <unistd.h>
#include <iostream>
#include <stdio.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <stdlib.h>
#include <cstring>
#include "Shell.h"
using namespace std;
class Cmd : public Shell
{
public:
Cmd(): Shell(NULL) {};
Cmd(char* userInput): Shell(userInput) {};
bool execute();
};
#endif
Cmd.cpp
#include "Cmd.h"
bool Cmd::execute()
{
char * list[1000];
bool status = true;
return status;
}
我对此进行了研究,发现它可能来自我的 makefile 或我的虚拟函数 我的虚函数被声明了
生成文件
COMPILE = g++
FLAGS = -Werror -Wall -ansi
all:
mkdir -p ./bin
$(COMPILE) $(FLAGS) ./src/main.cpp -o ./bin/rshell
main:
$(COMPILE) $(FLAGS) ./src/main.cpp
Cmd:
$(COMPILE) $(FLAGS) ./src/Cmd.cpp
Exit:
$(COMPILE) $(FLAGS) ./src/Exit.cpp
Connector:
$(COMPILE) $(FLAGS) ./src/Connector.cpp
And:
$(COMPILE) $(FLAGS) ./src/And.cpp
Or:
$(COMPILE) $(FLAGS) ./src/Or.cpp
Semi:
$(COMPILE) $(FLAGS) ./src/Semi.cpp
clean:
rm -rf ./bin
【问题讨论】:
-
显示的 makefile 已完全损坏。它试图将每个单独的翻译单元编译为独立的可执行文件,而不是将所有翻译单元链接到单个可执行文件中。
-
您需要将所有文件编译并链接到一个程序中。
-
我该怎么做呢?在线搜索提供了多种实现 makefile 的方法
-
@opera97
make(尤其是 GNU make)是非常强大的工具。因此,它允许您以多种不同的方式实现相同的效果。大多数在 Internet 上找到的 Makefile 都是由某些工具生成的,因此它们通常包含针对每个源文件的显式规则,例如:main.o: main.cpp shell.h后跟仅编译的命令main.cpp等。但是您实际上可以使用隐式规则编写非常通用的 Makefile,然后您只需更新源文件或预期目标文件的列表,隐式规则将使 make 找出必须编译/链接的内容以及如何。 -
无论如何,你应该花几天时间研究制作文档,学习一些基础知识。或者切换到其他构建系统(最终可能类似的复杂性,尽管开始可能更简单)或 IDE(通常更简单,只是功能不那么强大)。但这么多年过去了,我还是更喜欢 GNUmake。每当我看到新的构建系统(最近是“gradle”)时,我都会对自己说:“又一个程序员懒得学习制定规则,添加了另一个无用的构建系统”...... :/(然后谷歌为 Android Studio 选择了它我只是想知道,我是疯了,还是他们?还是在做噩梦?我想醒来......)
标签: c++ inheritance makefile