3

I'm trying to compile my project and getting multiple definition of function error:

CMakeFiles/OasisTest.dir/Tests/Oasis_test.cpp.o: In function `MinHeap::left(int)':
/home/d_/CODING/CLionProjects/DS1-Course_Wet2/Oasis-2/Tests/../DataStructures/MinHeap.h:56: multiple definition of `MinHeap::MinHeap(int)'
CMakeFiles/OasisTest.dir/Oasis.cpp.o:/home/d_/CODING/CLionProjects/DS1-Course_Wet2/Oasis-2/DataStructures/MinHeap.h:56: first defined here

It seems that I have variable definitions in my header file, and those should be removed or made extern, or made inline, but I don't have an idea what to change.

NOTE: I succeeding to compile without MinHeap.h

What I'm trying to compile as in CMakeLists.txt:

add_executable(OasisTest
        Oasis.cpp
        Tests/Oasis_test.cpp
        )

MinHeap.h

#ifndef OASIS_MINHEAP_H
#define OASIS_MINHEAP_H

#include <iostream>
#include <climits>

using namespace std;

// Prototype of a utility function to swap two integers
void swap(int* x, int* y);

// A class for Min Heap
class MinHeap {

    int* harr; // pointer to array of elements in heap
    int capacity; // maximum possible size of min heap
    int heap_size; // Current number of elements in min heap
public:
    // Constructor
    MinHeap(int cap);

    // to heapify a subtree with the root at given index
    void MinHeapify(int);

    int parent(int i) { return (i - 1) / 2; }

    // to get index of left child of node at index i
    int left(int i) { return (2 * i + 1); }

    // to get index of right child of node at index i
    int right(int i) { return (2 * i + 2); }

    // to extract the root which is the minimum element
    int extractMin();

    // Decreases key value of key at index i to new_val
    void decreaseKey(int i, int new_val);

    // Returns the minimum key (key at root) from min heap
    int getMin() { return harr[0]; }

    // Deletes a key stored at index i
    void deleteKey(int i);

    // Inserts a new key 'k'
    void insert(int k);

    bool isEmpty();
};

// Constructor: Builds a heap from a given array a[] of given size
MinHeap::MinHeap(int cap) {
    heap_size = 0;
    capacity = cap;
    harr = new int[cap];
}

// Inserts a new key 'k'
void MinHeap::insert(int k) {
    if (heap_size == capacity) {
        cout << "\nOverflow: Could not insert\n";
        return;
    }

    // First insert the new key at the end
    heap_size++;
    int i = heap_size - 1;
    harr[i] = k;

    // Fix the min heap property if it is violated
    while (i != 0 && harr[parent(i)] > harr[i]) {
        swap(&harr[i], &harr[parent(i)]);
        i = parent(i);
    }
}

// Decreases value of key at index 'i' to new_val.  It is assumed that
// new_val is smaller than harr[i].
void MinHeap::decreaseKey(int i, int new_val) {
    harr[i] = new_val;
    while (i != 0 && harr[parent(i)] > harr[i]) {
        swap(&harr[i], &harr[parent(i)]);
        i = parent(i);
    }
}

// Method to remove minimum element (or root) from min heap
int MinHeap::extractMin() {
    if (heap_size <= 0)
        return INT_MAX;
    if (heap_size == 1) {
        heap_size--;
        return harr[0];
    }

    // Store the minimum value, and remove it from heap
    int root = harr[0];
    harr[0] = harr[heap_size - 1];
    heap_size--;
    MinHeapify(0);

    return root;
}

// This function deletes key at index i. It first reduced value to minus
// infinite, then calls extractMin()
void MinHeap::deleteKey(int i) {
    decreaseKey(i, INT_MIN);
    extractMin();
}

// A recursive method to heapify a subtree with the root at given index
// This method assumes that the subtrees are already heapified
void MinHeap::MinHeapify(int i) {
    int l = left(i);
    int r = right(i);
    int smallest = i;
    if (l < heap_size && harr[l] < harr[i])
        smallest = l;
    if (r < heap_size && harr[r] < harr[smallest])
        smallest = r;
    if (smallest != i) {
        swap(&harr[i], &harr[smallest]);
        MinHeapify(smallest);
    }
}

bool MinHeap::isEmpty() {
    return heap_size <= 0;
}

// A utility function to swap two elements
void swap(int* x, int* y) {
    int temp = *x;
    *x = *y;
    *y = temp;
}

#endif //OASIS_MINHEAP_H

includes from Oasis.h

#include "library2.h" //Only typedefs
#include "DataStructures/HashTable.h" //Includes AVLTree.h
#include "DataStructures/AVLRankTree.h" //Include to AvlExceptions 
#include "DataStructures/MinHeap.h" 

Oasis.cpp

#include "Oasis.h"

Oasis_test.cpp

#include "TestMacros.h"
#include "../Oasis.h"

The full error:

CMakeFiles/OasisTest.dir/Tests/Oasis_test.cpp.o: In function `MinHeap::left(int)':
/home/d_/CODING/CLionProjects/DS1-Course_Wet2/Oasis-2/Tests/../DataStructures/MinHeap.h:56: multiple definition of `MinHeap::MinHeap(int)'
CMakeFiles/OasisTest.dir/Oasis.cpp.o:/home/d_/CODING/CLionProjects/DS1-Course_Wet2/Oasis-2/DataStructures/MinHeap.h:56: first defined here
CMakeFiles/OasisTest.dir/Tests/Oasis_test.cpp.o: In function `MinHeap::left(int)':
/home/d_/CODING/CLionProjects/DS1-Course_Wet2/Oasis-2/Tests/../DataStructures/MinHeap.h:56: multiple definition of `MinHeap::MinHeap(int)'
CMakeFiles/OasisTest.dir/Oasis.cpp.o:/home/d_/CODING/CLionProjects/DS1-Course_Wet2/Oasis-2/DataStructures/MinHeap.h:56: first defined here
CMakeFiles/OasisTest.dir/Tests/Oasis_test.cpp.o: In function `HashTable<int>::destroy_hash()':
/home/d_/CODING/CLionProjects/DS1-Course_Wet2/Oasis-2/Tests/../DataStructures/MinHeap.h:63: multiple definition of `MinHeap::insert(int)'
CMakeFiles/OasisTest.dir/Oasis.cpp.o:/home/d_/CODING/CLionProjects/DS1-Course_Wet2/Oasis-2/DataStructures/MinHeap.h:63: first defined here
CMakeFiles/OasisTest.dir/Tests/Oasis_test.cpp.o: In function `swap(int*, int*)':
/home/d_/CODING/CLionProjects/DS1-Course_Wet2/Oasis-2/Tests/../DataStructures/MinHeap.h:137: multiple definition of `swap(int*, int*)'
CMakeFiles/OasisTest.dir/Oasis.cpp.o:/home/d_/CODING/CLionProjects/DS1-Course_Wet2/Oasis-2/DataStructures/MinHeap.h:137: first defined here
CMakeFiles/OasisTest.dir/Tests/Oasis_test.cpp.o: In function `MinHeap::decreaseKey(int, int)':
/home/d_/CODING/CLionProjects/DS1-Course_Wet2/Oasis-2/Tests/../DataStructures/MinHeap.h:83: multiple definition of `MinHeap::decreaseKey(int, int)'
CMakeFiles/OasisTest.dir/Oasis.cpp.o:/home/d_/CODING/CLionProjects/DS1-Course_Wet2/Oasis-2/DataStructures/MinHeap.h:83: first defined here
CMakeFiles/OasisTest.dir/Tests/Oasis_test.cpp.o: In function `MinHeap::extractMin()':
/home/d_/CODING/CLionProjects/DS1-Course_Wet2/Oasis-2/Tests/../DataStructures/MinHeap.h:92: multiple definition of `MinHeap::extractMin()'
CMakeFiles/OasisTest.dir/Oasis.cpp.o:/home/d_/CODING/CLionProjects/DS1-Course_Wet2/Oasis-2/DataStructures/MinHeap.h:92: first defined here
CMakeFiles/OasisTest.dir/Tests/Oasis_test.cpp.o: In function `MinHeap::MinHeapify(int)':
/home/d_/CODING/CLionProjects/DS1-Course_Wet2/Oasis-2/Tests/../DataStructures/MinHeap.h:118: multiple definition of `MinHeap::MinHeapify(int)'
CMakeFiles/OasisTest.dir/Oasis.cpp.o:/home/d_/CODING/CLionProjects/DS1-Course_Wet2/Oasis-2/DataStructures/MinHeap.h:118: first defined here
CMakeFiles/OasisTest.dir/Tests/Oasis_test.cpp.o: In function `MinHeap::deleteKey(int)':
/home/d_/CODING/CLionProjects/DS1-Course_Wet2/Oasis-2/Tests/../DataStructures/MinHeap.h:111: multiple definition of `MinHeap::deleteKey(int)'
CMakeFiles/OasisTest.dir/Oasis.cpp.o:/home/d_/CODING/CLionProjects/DS1-Course_Wet2/Oasis-2/DataStructures/MinHeap.h:111: first defined here
CMakeFiles/OasisTest.dir/Tests/Oasis_test.cpp.o: In function `MinHeap::isEmpty()':
/home/d_/CODING/CLionProjects/DS1-Course_Wet2/Oasis-2/Tests/../DataStructures/MinHeap.h:132: multiple definition of `MinHeap::isEmpty()'
CMakeFiles/OasisTest.dir/Oasis.cpp.o:/home/d_/CODING/CLionProjects/DS1-Course_Wet2/Oasis-2/DataStructures/MinHeap.h:132: first defined here
Dennis Vash
  • 50,196
  • 9
  • 100
  • 118
  • 11
    Move every implementation of `MinHeap` member functions in a .cpp file or make them inline. – O'Neil Jun 11 '18 at 14:15
  • Have you tried one of the following: - move the declarations out of the header into a *.cpp file, or - removing the definitions and moving the declarations up to be in the correct visibility, i.e. `MinHeap::MinHeap(...)` becomes just `MinHeap(...)` under `public:`, inlined or header only. – vonludi Jun 11 '18 at 14:17
  • @O'Neil Thanks I moved all members to .cpp file – Dennis Vash Jun 11 '18 at 14:44

1 Answers1

10

You are defining each member in the header file itself; so each time you include the header file in your source code, these members are redefined; that is why you are getting multiple definition error. To resolve this either define each member function in the class itself or move the definitions from header file to a separate cpp file(like other people suggested) and add that cpp file to add_executable command.

Vikash Kesarwani
  • 850
  • 5
  • 14
  • 3
    ...or mark the member functions as `inline` (which happens automatically when you define the functions inside the class definition). – Max Langhof Jun 11 '18 at 14:37
  • What is so special about current `MinHeap.h` implementation, on my other DS I done the same thing, implement members in the same file – Dennis Vash Jun 11 '18 at 14:43
  • *To resolve this either define each member function in the class itself*, it answered my question thanks – Dennis Vash Jun 11 '18 at 14:46