Andrew
Andrew

Reputation: 3589

C++ multiple definition first defined here

I'm typing out an example program from Absolute C++ and it keeps giving me this error:

/tmp/ccJfp4DM.o: In function `HashTableSavitch::HashTable::HashTable()':
hashtableimp.cpp:(.text+0x0): multiple definition of `HashTableSavitch::HashTable::HashTable()'
/tmp/ccHuZlFl.o:hashtable.cpp:(.text+0x0): first defined here
/tmp/ccJfp4DM.o: In function `HashTableSavitch::HashTable::HashTable()':
hashtableimp.cpp:(.text+0x0): multiple definition of `HashTableSavitch::HashTable::HashTable()'
/tmp/ccHuZlFl.o:hashtable.cpp:(.text+0x0): first defined here
/tmp/ccJfp4DM.o: In function `HashTableSavitch::HashTable::~HashTable()':
hashtableimp.cpp:(.text+0x16): multiple definition of `HashTableSavitch::HashTable::~HashTable()'
/tmp/ccHuZlFl.o:hashtable.cpp:(.text+0x16): first defined here
/tmp/ccJfp4DM.o: In function `HashTableSavitch::HashTable::~HashTable()':
hashtableimp.cpp:(.text+0x16): multiple definition of `HashTableSavitch::HashTable::~HashTable()'
/tmp/ccHuZlFl.o:hashtable.cpp:(.text+0x16): first defined here
/tmp/ccJfp4DM.o: In function `HashTableSavitch::HashTable::~HashTable()':
hashtableimp.cpp:(.text+0x44): multiple definition of `HashTableSavitch::HashTable::~HashTable()'
/tmp/ccHuZlFl.o:hashtable.cpp:(.text+0x44): first defined here
/tmp/ccJfp4DM.o: In function `HashTableSavitch::HashTable::computeHash(std::string)':
hashtableimp.cpp:(.text+0x6a): multiple definition of `HashTableSavitch::HashTable::computeHash(std::string)'
/tmp/ccHuZlFl.o:hashtable.cpp:(.text+0x6a): first defined here
/tmp/ccJfp4DM.o: In function `HashTableSavitch::HashTable::containsString(std::string) const':
hashtableimp.cpp:(.text+0x7a): multiple definition of `HashTableSavitch::HashTable::containsString(std::string) const'
/tmp/ccHuZlFl.o:hashtable.cpp:(.text+0x7a): first defined here
/tmp/ccJfp4DM.o: In function `HashTableSavitch::HashTable::put(std::string)':
hashtableimp.cpp:(.text+0x8e): multiple definition of `HashTableSavitch::HashTable::put(std::string)'
/tmp/ccHuZlFl.o:hashtable.cpp:(.text+0x8e): first defined here
collect2: error: ld returned 1 exit status
Makefile:2: recipe for target 'hashTable' failed
make: *** [hashTable] Error 1

I've reduced the program down to its pure basics but I still can't figure out what's going on. Can anyone help?

Makefile:

hashTable: listtools.h listtools.cpp hashtable.h hashtable.cpp hashtableimp.cpp 
    g++ listtools.h listtools.cpp hashtable.h hashtable.cpp hashtableimp.cpp -o hashTable

hashtable.h

#ifndef HASHTABLE_H
#define HASHTABLE_H

#include <string>
#include "listtools.h"

using LinkedListSavitch::Node;
using std::string;

namespace HashTableSavitch {
    const int SIZE = 10;
    class HashTable {
    public:
        HashTable();
        virtual ~HashTable();
        bool containsString(string target) const;
        void put(string s);
    private:
        Node<string> *hashArray[SIZE];
        static int computeHash(string s);
    };
}

#endif

hashtable.cpp

#include <string>
#include "listtools.h"
#include "hashtable.h"

using LinkedListSavitch::Node;
using LinkedListSavitch::search;
using LinkedListSavitch::headInsert;
using std::string;

namespace HashTableSavitch {
    HashTable::HashTable() {

    }

    HashTable::~HashTable() {

    }

    int HashTable::computeHash(string s) {
        return 0;
    }
    bool HashTable::containsString(string target) const {
        return true;
    }

    void HashTable::put(string s) {

    }
} // HashTableSavitch

hashtableimp.cpp

#include <string>
#include <iostream>
#include "hashtable.h"
#include "listtools.cpp"
#include "hashtable.cpp"
using std::string;
using std::cout;
using std::endl;
using HashTableSavitch::HashTable;

int main() {
    HashTable h;
    cout << "Adding cat, dog, turtle, and bird" << endl;
    h.put("cat");
    h.put("dog");
    h.put("turtle");
    h.put("bird");

    cout << "Contains cat? " << h.containsString("cat") << endl;
    cout << "Contains dog? " << h.containsString("dog") << endl;
    cout << "Contains turtle? " << h.containsString("turtle") << endl;
    cout << "Contains bird? " << h.containsString("bird") << endl;
    cout << "Contains cow? " << h.containsString("cow") << endl;
    cout << "Contains fish? " << h.containsString("fish") << endl;

    return 0;
}

listtools.h

#ifndef LISTTOOLS_H
#define LISTTOOLS_H

namespace LinkedListSavitch {
    template<class T>
    class Node {
    public:
        Node(const T& theData, Node<T>* theLink) : data(theData), link(theLink) {}
        Node<T>* getLink() const {return link;}
        const T getData() const {return data;}
        void setData(const T& theData) {data = theData;}
        void setLink(Node<T>* pointer) {link = pointer;}
    private:
        T data;
        Node<T> *link;
    };

    template<class T>
    void headInsert(Node<T>*& head, const T& theData);

    template<class T>
    void insert(Node<T>* afterMe, const T& theData);

    template<class T>
    void deleteNode(Node<T>* before);

    template<class T>
    void deleteFirstNode(Node<T>*& head);

    template<class T>
    Node<T>* search(Node<T>* head, const T& target);
} // LinkedListSavitch

#endif

Upvotes: 1

Views: 11053

Answers (1)

Petr
Petr

Reputation: 10007

You should not #include cpp's into the main hashtableimp.cpp, if you want to list them on g++ command line.

Actually you have two options here:

  • Include all your code into one file (or split the code into several files and #include it one into another, so that it is effectively one file) — in such a case you need to list only this main file in g++ command line
  • Really split code across several files — then you list all these files on a g++ command line, but you do not need to #include files with definitions (usually cpp) into other files.

The reason is One Definition Rule: any function (with some exceptions) should be defined in one place in the whole program. If you #include one cpps into anothers, and then compile all of them, you repeat definitions.

Usually the former approach is used for small programs, and the latter for lager projects. Even more commonly, in latter approach you usually compile each file one by one, and then link them together.

Also note that you do not usually need to list .h files in the command line, they should not be compiled by themself, they are just to be #included into other .cpp files so that the compiler knows the declaration of functions/objects/etc used there.

Upvotes: 12

Related Questions