Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why am I getting these 'already defined' linker errors?

Tags:

c++

linker

I am a beginner at C++ but I have some experience using Java. I am getting some errors that I don't understand. I attached a pic of the error console and the code below it.

 Error  1   error LNK2005: "public: __thiscall VectorDouble::VectorDouble(void)" (??0VectorDouble@@QAE@XZ) already defined in Main.obj  C:\Users\carrea\Code\Visual Studio\COMP201\Lab8_VectorDoubleClass\VectorDouble.obj  Lab8_VectorDoubleClass

 Error  2   error LNK2005: "public: __thiscall VectorDouble::VectorDouble(int)" (??0VectorDouble@@QAE@H@Z) already defined in Main.obj  C:\Users\carrea\Code\Visual Studio\COMP201\Lab8_VectorDoubleClass\VectorDouble.obj  Lab8_VectorDoubleClass
....    

10 more errors like these and

 Error  13  error LNK1169: one or more multiply defined symbols found   C:\Users\carrea\Code\Visual Studio\COMP201\Lab8_VectorDoubleClass\Debug\Lab8_VectorDoubleClass.exe  1   1   Lab8_VectorDoubleClass

Main.cpp


#include "VectorDouble.cpp"
using namespace std;
void printVD(const VectorDouble& v);
int main()
{
    VectorDouble p;
    p.push_back(1);
    p.push_back(4);
    p.push_back(3);
    VectorDouble v(p);
    printVD(v);
    printVD(p);
}
void printVD(const VectorDouble& v)
{
    int n = v.size();
    for(int i = 0; i<n; i++)
    {
        cout << v.getElementAt(n) << " ";
    }
    cout << endl;
}

VectorDouble.h


#pragma once
#include <fstream>
#include <iostream>
#include <string>
#include <cstdlib>
#include <iomanip>
#include <vector>
#include <sstream>
using namespace std;
class VectorDouble
{
public:
    VectorDouble(void);
    ~VectorDouble(void);
    VectorDouble(int intSize);
    // Copy constructor
    VectorDouble(const VectorDouble& vd);
    // = override
    void operator =(const VectorDouble& RIGHT_SIDE);
private:
    double *dArray;
    int count, max_count;
public:
    // returns number of occupied cells
    int size(void) const;
    // Returns total number of cells
    int capacity(void) const;
    // Adds an element to array
    void push_back(double num);
    // Resizes the array to be double the original max_count
    void resize(void);
    // Returns element at specified index
    double getElementAt(int i) const;
    // Requests that the capacity of the allocated storage space for the elements of the vector container be at least enough to hold n elements
    void reserve(int n);
private:
    // Sets every element to 0
    void clear(void);
};

VectorDouble.cpp


    #pragma once
#include "VectorDouble.h"

using namespace std;

VectorDouble::VectorDouble(void)
{
    max_count = 100;
    count = 0;
    dArray = new double[max_count];
    clear();
}

VectorDouble::VectorDouble(int intSize)
{
    max_count = intSize;
    dArray = new double[max_count];
    clear();
}

VectorDouble::~VectorDouble(void)
{
    cout << "vector with " << this->count << " is destroyed";
}

// Copy constructor
VectorDouble::VectorDouble(const VectorDouble& vd) 
{
    int mcVD = vd.capacity(), i=0;
    max_count = mcVD;
    dArray = new double[max_count];
    clear();
    while(i<max_count)
    {
        dArray[i] = vd.getElementAt(i);
        i++;
    }
}
// = override
void VectorDouble::operator =(const VectorDouble& RIGHT_SIDE)
{
    int rightCount = RIGHT_SIDE.size(), i=0;
    while(rightCount>max_count)
    {
        resize();
    }
    while(i<rightCount)
    {
        dArray[i] = RIGHT_SIDE.getElementAt(i);
        i++;
    }
    count = i;
}
// returns number of occupied cells
int VectorDouble::size(void) const
{
    return count;
}
// Returns total number of cells
int VectorDouble::capacity(void) const
{
    return max_count;
}
// Adds an element to array
void VectorDouble::push_back(double num)
{
    if(count==max_count)
    {
        resize();
    }
    dArray[count] = num;
    count++;
}
// Resizes the array to be double the original max_count
void VectorDouble::resize(void)
{
    double *p = new double[max_count*2];
    for(int i = 0; i < count; i++)
    {
        p[i] = dArray[i];
    }
    dArray = p;
    max_count*=2;
    delete p;
}


// Returns element at specified index
double VectorDouble::getElementAt(int i) const
{
    return dArray[i];
}


// Requests that the capacity of the allocated storage space for the elements of the vector container be at least enough to hold n elements
void VectorDouble::reserve(int n)
{
    while(n<max_count)
        resize();
}


// Sets every element to 0
void VectorDouble::clear(void)
{
    for(int i = 0; i < max_count; i++)
        dArray[i] = 0;
}

Any help would be much appreciated...

like image 793
SomethingsGottaGive Avatar asked Mar 17 '11 00:03

SomethingsGottaGive


1 Answers

You should include "VectorDouble.h" and not "VectorDouble.cpp" in Main.cpp.

The whole concept of include files is rather broken in C++ as compared to many other languages.

First C++ divides things up into 'declarations' and 'definitions'. You may only ever have one definition of something in a program, but as many declarations as you want. In your VectorDouble.cpp file you are defining things, and in VectorDouble.h file you are declaring things.

The #include directive in C++ is dead simple and stupid. When it is encountered the compiler effectively does a simple textual replacement. The #include directive is replaced with the contents of the file you are including.

When you #include a file of definitions, that means you effectively define them all right there where you've done the #include. This is why you shouldn't be including "VectorDouble.cpp". Since you likely also compile that file as a separate file, you then end up with at least two copies of all the definitions right there.

This whole declaration vs. definition dichotomy gets very confusing when talking about certain kinds of things. For example, if a function is declared inline the function body isn't really considered a definition anymore, exactly. This means you can have as many copies of a function body that's been declared inline as you want. All that's required is that all of the definitions be identical.

Similarly, declaring a template function is a declaration, even if you include a function body. This is because the declaration results in no code being generated, only the template instantiation results in code generation. And that's the real litmus test for deciding if something is a declaration or definition. If it results in space being allocated or actual code being produced right then and there, then its a definition, otherwise its a declaration.

like image 79
Omnifarious Avatar answered Oct 25 '22 01:10

Omnifarious