0

I'm learning a new Language C++ with knowledge used from Java not JavaScript. I'm trying to make a Parent class called Command with a derived class CmdHelp. In java I would make an abstract class called Command.java, and make the class CmdHelp.java extend to Command, and in the constructor of CmdHelp.java I would have a static ArrayList<Command> inside of Command.java that will add it's self like this.

public CmdHelp() {
    // Set protected variables here like label, usage, and description for the CmdHelp class.
    cmds.add(this);
}

This is Java, and I'm trying to mirror this into C++. When I created a static vector<class Command> variable in the Command.h header file, and then in the CmdHelp.cpp constructor, and did

CmdHelp::CmdHelp() {
    cmds.push_back((Command) *this);
}

It doesn't seem to add the instance to the vector list. Bellow is all my C++ code, and files.

main.cpp

#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include "Command.h"

using namespace std;

int main() {
    cout << "Initiated Command Line:" << endl;
    while (true) {
        cout << "> ";
        string input = "";
        cin >> input;
        bool found = Command::checkCommand(input);
        if (found) {
            Command::getCommand(input).run();
        }
        else {
            Command::printNotFound();
        }
    }
    return 0;
}

Command.h

#include <iostream>
#include <string>
#include <vector>

using namespace std;

class Command {
public:
    Command();
    // VARIABLES //
    string label;
    string usage;
    string description;
    // STATIC VARIABLES //
    static vector<class Command> cmds;
    // SETTER FUNCTIONS //
    void setLabel(string);
    void setUsage(string);
    void setDescription(string);
    // GETTER FUNCTIONS //
    string getLabel();
    string getUsage();
    string getDescription();
    // INHERIT FUNCTIONS //
    virtual void run(); // trying to make this function an "abstract" function like I would in Java.
    // STATIC FUNCTIONS //
    static Command getCommand(string);
    static bool checkCommand(string);
    static void printNotFound();
};

Command.cpp

#include "Command.h"
#include <iostream>
#include <string>

using namespace std;

Command::Command() {
}

// SETTER FUNCTIONS //
void Command::setLabel(string label) {
    Command::label = label;
}

void Command::setUsage(string usage) {
    Command::usage = usage;
}

void Command::setDescription(string description) {
    Command::description = description;
}

// GETTER FUNCTIONS //
string Command::getLabel() {
    return label;
}
string Command::getUsage() {
    return usage;
}
string Command::getDescription() {
    return description;
}

void Command::run() {}

// STATIC FUNCTIONS //
Command Command::getCommand(string label) {
    for (int i = 0; i < cmds.size(); i++) {
        if (cmds[i].getLabel() == label) {
            return cmds[i];
        }
    }
    return Command();
}
bool Command::checkCommand(string label) {
    for (int i = 0; i < cmds.size(); i++) {
        if (cmds[i].getLabel() == label) {
            return true;
        }
    }
    return false;
}
void Command::printNotFound() {
    cout << "Command not found! Type \"help\"!" << endl;
}

CmdHelp.h

#include "Command.h"

class CmdHelp: public Command {
public:
    CmdHelp();
    void run();
};

CmdHelp.cpp

#include "CmdHelp.h"
#include <iostream>
#include <string>

using namespace std;

CmdHelp::CmdHelp() {
    setLabel("HELP");
    setUsage("/help");
    setDescription("Shows the help screen!");
    cmds.push_back((Command) *this);
}

void CmdHelp::run() {
    cout << cmds[0].getLabel() << endl;
}

Please help me it gives these weird errors. And sorry if this is SUPER simple, I can't find a solution because I don't know what this is even called? This is only my first week of C++ when I know Java for 5 years. Please do Java references so I can understand easier.

THANK YOU.

Here are my errors:

1>CmdHelp.obj : error LNK2001: unresolved external symbol "public: static class std::vector > Command::cmds" (?cmds@Command@@2V?$vector@PEAVCommand@@V?$allocator@PEAVCommand@@@std@@@std@@A)

1>Command.obj : error LNK2001: unresolved external symbol "public: static class std::vector > Command::cmds" (?cmds@Command@@2V?$vector@PEAVCommand@@V?$allocator@PEAVCommand@@@std@@@std@@A)

1>C:\Users\Dennis\Documents\Projects\CPPTutorial\CPPTutorial\x64\Debug\CPPTutorial.exe : fatal error LNK1120: 1 unresolved externals

  • 1
    Yes you mention Java, but that doesn't make this a Java question, and in fact, it is not, and so I've removed your [tag:java] tag to avoid any confusion. – Hovercraft Full Of Eels Mar 07 '16 at 22:28
  • Don't try to mimic Java in C++, it will end up badly. Do not assume similar looking constructs in C++ do the things they do in Java, it will end badly. Do not assume you can code in C++ because you know Java, it will end badly. Go back to you book, forget all that you know about Java and start reading about C++. – SergeyA Mar 07 '16 at 22:29
  • Thanks I'll just "wipe out" my Java experience and only practice C++ so I can get the jist. – DennisOfficial Mar 08 '16 at 22:39

1 Answers1

2

First bit of unexpected nasty you've likely run across is

static vector<class Command> cmds;

This says there is a static vector of Commands. It doesn't allocate any space for it, so in one of the CPP files, Command.cpp looks like the logical place, you have to allocate storage for the sucker with

vector<Command> Command::cmds;

You don't have to write class Command, the class is implied by Command being a class. But since you intend to pack this vector with children of Command, you probably want

static std::vector<std::unique_ptr<Command>> cmds;

and

vector<std::unique_ptr<Command>> Command::cmds;

Otherwise you get a vector of Command and the children you store will get sliced.

Documentation on std::unique_ptr.

You could use

static std::vector<Command*> cmds;

but this leaves you with a bunch of memory that needs to be cleaned up when you remove commands from cmds and on program exit. C++ does not clean up after you like Java does.

The next bit is Include Guards. You might have left just these out, but DON'T. #include basically means, "Paste the named file in here before compiling". Include Guards prevent the same file from being included more than once and wreaking havoc with infinite include loops, duplicate definitions and other badness.

Here is some reading on the Include Guard:

Wikipedia page,

C++ #include guards

And if there are more problems you'll have to list what "weird errors" you're getting.

Oh. One more java to c++ thing. In java, everything is virtual unless final. I think it's final. Been a while since I've done Java. In C++, nothing is virtual unless you say it is. This means you are gong to run into destructor nastiness because you didn't declare a virtual destructor for Command.

virtual ~ Command()
{
    // does nothing
}

Without it, the wrong destructors, or not enough of them, will run.

using namespace std; is bad. It is very bad in headers: Why is "using namespace std" considered bad practice?

Community
  • 1
  • 1
user4581301
  • 33,082
  • 7
  • 33
  • 54
  • I'm still getting the same errors. It's not telling me what line it just saids the error is in the exe file. – DennisOfficial Mar 08 '16 at 22:46
  • That's because the linker doesn't know lines. By the time the linker gets to do it's job it's working on compiled objects and either a name is present in the object file or it isn't. Did you place `vector Command::cmds;` in Command.cpp? – user4581301 Mar 08 '16 at 23:37