2010-11-03 26 views
0

Je comprends le problème que j'ai avec mon code, mais essayer certaines des choses que d'autres suggèrent ne corrige pas mon erreur.Redéfinition des types de classes - C++

Voilà mes messages d'erreur:

In file included from proj07.driver.cpp:4: 
proj07.string.cpp:10: error: redefinition of 'String::String()' 
/user/cse232/Projects/project07.string.h:25: error: 'String::String()' previously defined here 
proj07.string.cpp: In constructor 'String::String(const char*)': 
proj07.string.cpp:19: error: expected primary-expression before 'char' 
proj07.string.cpp:19: error: expected `;' before 'char' 
make: *** [proj07.driver.o] Error 1 

Voici celui que je suis inquiet:

proj07.string.cpp:10: error: redefinition of 'String::String()' 
/user/cse232/Projects/project07.string.h:25: error: 'String::String()' previously defined here 

Je sais que je suis censé avoir mon fichier d'interface défini une fois, mais je ne suis pas Je suis sûr de ce qu'il faut changer car tout ce que j'essaie apporte plus de problèmes.

Mon chauffeur (proj07.driver.cpp):

using namespace std; 

#include <iostream> 
#include "proj07.string.cpp" 

int main() 
{ 
    const char string1[] = {'a', 'b', 'c', 'd', 'e', 'f'}; 
    String test1(); 
    String test2(string1); 
} 

Mon fichier support (proj07.support.cpp):

/* Implementation file for type "String" */ 

using namespace std; 

#include <iostream> 
#include "/user/cse232/Projects/project07.string.h" 

/*Default constructor*/ 

String::String() 
{ 
    Capacity = 0; 
    Length = 0; 
    Mem = NULL; 
} 

String::String(const char[]) 
{ 
    cout << char.length[]; //Function not implemented yet 
} 

Mon makefile:

# 
# Project 07 
# 

proj07.exe: proj07.driver.o proj07.string.o 
     g++ -o proj07.exe proj.driver. proj07.string.o 

proj07.driver.o: proj07.driver.cpp ~cse232/Projects/project07.string.h 
     g++ -Wall -c proj07.driver.cpp 

proj07.string.o: proj07.string.cpp ~cse232/Projects/project07.string.h 
     g++ -Wall -c proj07.string.cpp 

clean: 
     rm -f proj07.*.o proj07.exe 

Et le fichier d'en-tête - celui-ci comprend beaucoup de fonctions de classe que je n'ai pas encore faites. C'est inaltérable.

/****************************************************************************** 
    Project #7 -- Interface file for type "String" 
******************************************************************************/ 

#ifndef STRING_ 
#define STRING_ 

using namespace std; 

#include <iostream> 

class String 
{ 
    private: 

    unsigned Capacity; // Number of memory locations reserved 
    unsigned Length; // Number of memory locations in use 
    char * Mem;   // Pointer to memory to hold characters 

    public: 

    // Construct empty string 
    // 
    String() 
    { 
     Capacity = 0; 
     Length = 0; 
     Mem = NULL; 
    } 

    // Reset string to empty 
    // 
    void reset() { Length = 0; } 

    // Return string capacity and length 
    // 
    unsigned capacity() const { return Capacity; } 
    unsigned length() const { return Length; } 

    // Return string status 
    // 
    bool empty() const { return Length == 0; } 

    // Return reference to element I 
    // 
    char& operator[](unsigned I) { return Mem[I]; } 

    // Return constant reference to element I 
    // 
    const char& operator[](unsigned I) const { return Mem[I]; } 

    // Destroy string 
    // 
    ~String(); 

    // Construct string by copying existing string 
    // 
    String(const String&); 

    // Construct string by copying C-style character string 
    // 
    String(const char[]); 

    // Copy string into the current string 
    // 
    String& operator=(const String&);         

    // Append string to the current string 
    // 
    String& operator+=(const String&); 
}; 

// Return string which is the concatenation of two strings 
// 
String operator+(const String&, const String&); 

// Compare two strings (equality and relational operators) 
// 
bool operator==(const String&, const String&); 
bool operator< (const String&, const String&); 

// Output string to stream 
// 
ostream& operator<<(ostream&, const String&); 

// Input string from stream 
// 
istream& operator>>(istream&, String&); 

#endif 

Je comprends le problème a quelque chose à voir avec mes déclarations #include, mais je suis mêlé à propos de ceux qui à changer. Si quelqu'un peut me montrer ce que je fais mal, je serais très reconnaissant. Je vous remercie!

+0

S'il s'agit de devoirs, indiquez-le comme tel et, si ce n'est pas le cas, utilisez 'std :: string'! –

+0

Quelques commentaires sans rapport avec votre problème: Vous ne pouvez pas 'utiliser namespace' un espace de noms qui n'existe pas encore, donc si vous voulez' using namespace std', vous devez le faire _after_ vous incluez l'un des en-têtes de bibliothèque standard. Vous devriez préférer ne pas utiliser de directives, du moins pas du tout pour l'espace de noms, et ne pas l'utiliser dans un en-tête. Si vous l'utilisez dans un fichier d'en-tête, chaque fichier source contenant cet en-tête est bloqué avec 'using namespace std;'. En général, vous ne devriez pas l'utiliser car cela rend le code plus difficile à comprendre et peut rendre difficile le diagnostic des erreurs de recherche de noms. –

+0

De même, "#include " semble inutile dans ce cas. Si vous avez seulement besoin de la déclaration de 'ostream' et' istream' pour les opérateurs '<<' and '>>', #include 'devrait suffire. –

Répondre

6
#include "proj07.string.cpp" 

Vous devez inclure le fichier d'en-tête, pas le fichier .cpp. Si vous incluez le fichier .cpp, qui contient probablement des définitions, dans plusieurs fichiers .cpp, puis lorsque vous générez, vous obtiendrez plusieurs définitions erreurs (car les choses sont définies plusieurs fois dans différents fichiers .cpp).

+0

+1 Bien repéré! –

+0

Oh ouais! J'ai essayé cela en incluant le dossier d'en-tête n'a pas fonctionné. Mais j'ai changé cette ligne en arrière le fichier .h et a pris l'une des définitions de mon fichier de support, et cela fonctionne maintenant. Je vous remercie! :) –

4

En plus de ce que James McNellis dit, vous avez défini le constructeur par défaut à deux endroits différents:

En project07.string.h:

class String 
{ 
    private: 

    unsigned Capacity; // Number of memory locations reserved 
    unsigned Length; // Number of memory locations in use 
    char * Mem;   // Pointer to memory to hold characters 

    public: 

    // Construct empty string 
    // 
    String() 
    { 
     Capacity = 0; 
     Length = 0; 
     Mem = NULL; 
    } 
    /* ... */ 
}; 

Et dans proj07.support.cpp:

#include "/user/cse232/Projects/project07.string.h" 

/*Default constructor*/ 

String::String() 
{ 
    Capacity = 0; 
    Length = 0; 
    Mem = NULL; 
} 

Depuis que vous avez inclus string.h dans support.cpp, le compilateur voit deux implémentations différentes s du constructeur par défaut String, qui enfreint la règle de définition unique.


Certains commentaires sans rapport avec votre problème:

Je sais que vous ne pouvez pas modifier project07.string.h, mais il ne devrait vraiment pas avoir un using namespace std comme ça en elle. Cela fait en sorte que tout fichier contenant project07.string.h aura l'intégralité de l'espace de noms std, augmentant ainsi la probabilité de conflit entre l'un de vos identifiants.

En outre, il semble que la déclaration de classe nécessite uniquement une déclaration directe de ostream et istream. Dans ce cas, vous devez seulement #include <iosfwd>, au lieu de <iostream> entier.

+0

C'était tout! Je n'ai pas remarqué que c'était l'une des fonctions incluses dans le fichier .h. Je vous remercie! :) –

1

Votre constructeur String est, comme les états du message, défini deux fois. Une fois dans la définition de la classe:

class String { 
    // Construct empty string 
    // 
    String() 
    { 
     Capacity = 0; 
     Length = 0; 
     Mem = NULL; 
    } 
}; 

et une fois dans le fichier string.cpp, en tant que tel:

String::String() 
{ 
    Capacity = 0; 
    Length = 0; 
    Mem = NULL; 
} 

En outre, vous pouvez inclure string.h dans votre programme principal, pas main.cpp ou vous obtiendrez éditeur de liens des erreurs avec votre fichier makefile actuel.