-2

I have been starting to write a mock shell program but came into an issue right away. I am getting a undefined reference to `vtable for Cmd' when compiling my project

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;
}

I researched this and i found out it could be from my makefile or my virtual functions my virtual function is declared

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
opera97
  • 31
  • 1
  • 5
  • 1
    The shown makefile is completely broken. It's trying to compile each individual translation unit as a standalone executable, instead of linking all translation units into a single executable. – Sam Varshavchik Oct 28 '16 at 02:04
  • You need to compile and link all of the files into *one* program. – user253751 Oct 28 '16 at 02:06
  • How would i go about that? Online seadching gives a wide variety to implement makefiles – opera97 Oct 28 '16 at 02:34
  • @opera97 the `make` (especially GNU make) is very powerful tool. As such it allows you to achieve same effect in many different ways. Most of the Makefiles to be found on Internet are generated by some tool, thus they often contain explicit rule for every source file like: `main.o: main.cpp shell.h` followed by command to compile only `main.cpp` and similar. But you can actually write quite universal Makefile with implicit rules, where you then only update list of source files or expected object files, and the implicit rules will make the *make* figure out what has to be compiled/link and how. – Ped7g Oct 29 '16 at 01:49
  • Anyway, you should dive into make documentation for few days, to learn some basics. Or switch to some other build system (in the end probably similar complexity, although getting started may be simpler) or IDE (usually simpler, just less powerful). But after all those years I still prefer GNUmake. And whenever I see new build system (lately "gradle"), I think to myself: "one more programmer too lazy to learn make rules, adding yet another useless build system" ... :/ (then Google picks it for Android Studio and I just wonder, am I insane, or them? Or in some nightmare? I want to wake up...) – Ped7g Oct 29 '16 at 01:58

1 Answers1

0

The error means you are missing a reference to the first virtual method in the class.

The problem is you hosed your makefile.

General form of the solution is as follows:

CXX=g++ -Werror -Wall -ansi -c
LD=g++
OBJS=/src/main.o src/Cmd.o src/Exit.o src/Connector.o src/And.o src/Or.o src/Semi.o

all: .PHONY
        mkdir bin
        $(LD) -o bin/rshell $(OBJS)

%.o: %.cpp Shell.h Cmd.h
        $(CXX) $(FLAGS) -o $@ $<

There's a couple of things going on here.

  1. Use of OBJS and a rule to save lots of typing.
  2. compiling each .cpp file with -c to avoid trying to link too soon.
  3. Linking as the last step doesn't compile anything.
  4. Use of .PHONY so compile doesn't choke if somebody made a file called all.
Ped7g
  • 16,236
  • 3
  • 26
  • 63
Joshua
  • 40,822
  • 8
  • 72
  • 132