8
votes

Pourquoi est-ce que je reçois ces erreurs de liaison "déjà définies"?

Je suis un débutant à C ++ mais j'ai une certaine expérience en utilisant Java. Je reçois des erreurs que je ne comprends pas. J'ai joint une photo de la console d'erreur et le code ci-dessous.

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


3 commentaires

Ne devriez-vous pas #incluez "vecteur double.h" dans main.cpp au lieu de "vecteur double.c ++"?


Copier également l'affectation n'est pas correctement implémenté ( Opérateur vide = (const Vectordouble et droit_side); ). Il est censé renvoyer une référence, en général.


Votre problème est confus sur la distinction entre «déclaration» et «définition», car cette distinction n'existe pas en Java. Voir ma réponse.


4 Réponses :


7
votes

L'erreur que vous obtenez est une erreur de liaison qui vous indique que le compilateur trouve plusieurs définitions pour certaines fonctions membres. Si vous regardez ce morceau du message d'erreur:

#include "VectorDouble.h"


3 commentaires

Je ne pense pas que ce soit une réponse très bonne (mais pas -1 non bonne), car elle n'explique pas pourquoi il existe des fichiers «source» et des fichiers «en-tête». Il s'agit d'une distinction très étrange et parmi les langues couramment utilisées modernes n'existe que dans C et C ++. Il mérite une explication, en particulier pour quelqu'un qui est un programmeur Java.


Ce n'est pas une distinction étrange et est présente sous une forme dans toutes les langues conçues pour une programmation à grande échelle. Vous souhaitez généralement conserver l'interface spécifiée dans un fichier distinct de la mise en œuvre.


@James Kanze: Il n'existe pas en Java, ni en Python, Ruby, Perl, PHP ou Lisp, Erlang ou Ocaml. En fait, dans toutes les langues que j'ai utilisées pour tout grave au cours des 10 dernières années, C et C ++ ont été les seules qui ont eu la distinction.



2
votes

Main.CPP ne devrait pas être #include -ing votordouble.cpp; Il devrait #include votordouble.h. Si vous reliez des fichiers .cpp. CPPP, le linker consiste à tout voir à Vetordouble.cpp deux fois (une fois seul, et une fois quand il est #include -D de MAIN.CPP).


0 commentaires

32
votes

Vous devez inclure "vectordouble.h" et non "vectordouble.cpp" in main.cpp . .

Le concept entier d'inclure les fichiers est plutôt cassé en C ++ par rapport à de nombreuses autres langues.

premier C ++ divise les choses dans les «déclarations» et les «définitions». Vous n'avez peut-être jamais une définition de quelque chose dans un programme, mais autant de déclarations que vous le souhaitez. Dans votre fichier votordouble.cpp Vous définissez des choses, et dans votordouble.h fichier que vous déclarez des choses.

Le #include La directive en C ++ est morte simple et stupide. Lorsqu'il est rencontré, le compilateur fait effectivement un simple remplacement textuel. La directive #include est remplacée par le contenu du fichier que vous y comprend.

Lorsque vous #include un fichier de définitions, cela signifie que vous les définissez efficacement toutes là où vous avez effectué le #include . C'est pourquoi vous ne devriez pas inclure "vectordouble.cpp" . Puisque vous avez probablement compilé ce fichier en tant que fichier séparé, vous vous retrouvez avec au moins deux copies de toutes les définitions là-bas.

Toute cette déclaration vs Définition La dichotomie devient très déroutante lorsque vous parlez de certains types de choses. Par exemple, si une fonction est déclarée inline , le corps de la fonction n'est pas vraiment considéré comme une définition , exactement. Cela signifie que vous pouvez avoir autant de copies d'un organisme de fonction déclaré en ligne comme vous le souhaitez. Tout ce qui est nécessaire, c'est que toutes les définitions soient identiques.

De même, déclarer une fonction de modèle est une déclaration, même si vous incluez un organisme de fonction. En effet, la Déclaration n'entraîne aucun code généré, seule l'instanciation des modèles entraîne la génération de code. Et c'est le vrai test LitsMus pour décider si quelque chose est une déclaration ou une définition. S'il produit dans l'espace étant alloué ou que le code réel est produit à ce moment et là, alors sa définition, sinon sa déclaration.


0 commentaires

1
votes

J'ai eu une erreur de liaison similaire lorsque j'ai essayé de définir une classe dans un fichier distinct nommé présentementdatraduct.h em> et a également créé un fichier présageAserCtruct.cpp em>.

Voici le contenu de présageAserCuct.h em>: p> xxx pré>

tandis que dans présageAserCtruct.cpp em> il a une ligne : P>

void CPresentDataStruct::SomeActionOnData()
{
    //TO DO here
}

CPresentDataStruct::CPresentDataStruct()
{
}

CPresentDataStruct::~CPresentDataStruct()
{
}


0 commentaires