2010-11-18 6 views
0

J'ai un véhicule de classe (vehicle.h et vehicle.cpp). Visual Studio me donne des erreurs si je ne mets pas les inclus dans le fichier d'en-tête. Pourquoi est-ce? Dans mes deux missions précédentes, j'ai mis les inclus dans le fichier .cpp et n'ai eu aucun problème. Voici ce que je veux travailler, mais n'est pas:C++ où placer comprend

vehicle.h:

#ifndef VEHICLE_H 
#define VEHICLE_H 

using namespace std; 
class Vehicle 
{ 
public: 
    Vehicle(); 
    Vehicle(string mfr, int cylinders, Person owner); 
    string getManufacturer(); 
    int getNumOfCylinders(); 
    Person getOwner(); 
private: 
    string manufacturer; 
    int numOfCylinders; 
    Person owner; 
}; 
#endif 

vehicle.cpp:

#include <iostream> 
#include <string> 
using namespace std; 
#include "person.h" 
#include "vehicle.h" 

Vehicle::Vehicle() 
{ 
    //Initialize with defaults 
} 
Vehicle::Vehicle(string mfr, int cylinders, Person owner) 
{ 
    //Initialize with parameters 
} 
string Vehicle::getManufacturer() 
{ 
    return manufacturer; 
} 
int Vehicle::getNumOfCylinders() 
{ 
    return numOfCylinders; 
} 
Person Vehicle::getOwner() 
{ 
    return owner; 
} 

Person.h:

#ifndef PERSON_H 
#define PERSON_H 
class Person { 
    public: 
     //default constructor 
     Person(); 
     //constructor with two parameters 
     Person(string the_name, string no); 
     //accessor member functions 
     string get_name() const; 
     string getDriverLicenseNo() const; 
     //overloaded equal operator 
     bool operator==(const Person& p); 

     //overloaded extraction operator 
     friend istream& operator >> (istream& in, Person& p); 
     //overloaded insertion operator 
     friend ostream& operator <<(ostream& out, Person& p); 
    private: 
     string name; 
     string drivingLicenseNo; 
}; 
#endif 

personne .cpp:

#include <iostream> 
#include <string> 
using namespace std; 
#include "person.h" 


//default constructor 
Person::Person(){} 
//constructor with two parameters 
Person::Person(string the_name, string no){} 
//accessor member functions 
string Person::get_name() const 
{ 
    return name; 
} 
string Person::getDriverLicenseNo() const 
{ 
    return drivingLicenseNo; 
} 
//overloaded equal operator 
bool Person::operator==(const Person& p) 
{ 
    return false; 
} 

//overloaded extraction operator 
istream& operator >> (istream& in, Person& p) 
{ 
    return in; 
} 
//overloaded insertion operator 
ostream& operator <<(ostream& out, Person& p) 
{ 
    return out; 
} 

truck.h:

#include "vehicle.h" 
class Truck: public Vehicle 
{ 

}; 

truck.cpp:

#include "person.h" 
#include "vehicle.h" 
//implement truck here 

Couple d'erreurs par exemple:

erreur C2061: erreur de syntaxe: identificateur 'chaîne'

erreur C2146: erreur de syntaxe: manquant ';' avant identificateur 'getManufacturer'

erreur C2061: erreur de syntaxe: identificateur 'chaîne' erreur C2535: 'personne :: personne (void)': fonction membre déjà définie ou déclarée
erreur C2146: erreur de syntaxe: manquant « ; ' avant l'identificateur 'get_name'

erreur C4430: spécificateur de type manquant - int supposé. Remarque: C++ ne prend pas en charge default-int

erreur C4430: spécificateur de type manquant - int supposé. Remarque: C++ ne prend pas en charge default-int

erreur C2146: erreur de syntaxe: manquant ';' avant l'identificateur 'getDriverLicenseNo'

+1

Quelles sont les erreurs? –

+0

Pouvez-vous s'il vous plaît mettre les messages d'erreur comme des commentaires dans le code, de sorte que nous savons de quelle ligne chacun parle? –

+0

Bien sûr, ce n'est pas un problème je suppose, mais à ce stade, sans bouger quelque chose, j'ai un total de 41 erreurs. Y a-t-il un moyen d'obtenir du studio visuel pour le mettre dans le code d'une façon ou d'une autre? Les erreurs disparaissent quand je déplace les inclusions donc je suis presque sûr que c'est tout. Je veux juste comprendre comment le faire correctement et ne pas se battre avec le compilateur à chaque fois. – Pete

Répondre

3

Vous déclarez une instance de Person dans le fichier d'en-tête de votre véhicule. Le compilateur a donc besoin de la déclaration complète. Si vous utilisiez un pointeur ou une référence à une personne, vous pouviez simplement transmettre le déclarer avec class Person;.

EDIT: En outre, supprimez ce using namespace std; et préfixez vos variables avec std::. Cela permettra d'économiser beaucoup de balles à l'avenir.

EDIT2: Vous devez également inclure <string> dans votre fichier d'en-tête.

Ok, ici, je vais essayer de le garder agréable et simple. Lorsque votre compilateur traite vos fichiers d'implémentation (.cpp), il inclut les en-têtes que vous avez spécifiés (dans ce cas, il s'agit de vehicle.h et person.h).

Pour chaque fichier d'implémentation, le compilateur doit connaître chaque type que vous utilisez pour générer le code correct.

Lorsqu'il traite un fichier d'inclusion, il doit toujours savoir . Donc, dans votre fichier d'en-tête vehicle.h, vous utilisez Person. Au moment où le compilateur frappe cela, il doit savoir comment construire la personne. Votre vehicle.cpp comprend person.h avant vehicle.h donc pas de problème. POUR vehicle.cpp. Tout ce qui inclut vehicle.h mais n'inclut pas person.h, vous donnera des erreurs de compilation.

Alors, quand pouvez-vous vous en sortir avec une déclaration directe et un pointeur ou une référence?

La déclaration d'un pointeur ou d'une référence ne nécessite pas de dire au compilateur quoi que ce soit à propos de cette classe ou structure dans le fichier d'en-tête. Vous dites simplement au compilateur que vous avez l'intention de le faire. A condition que la classe est déclarée avant thusly:

class Person; 

le compilateur dit « okee dokee, je vais prendre ça. » Ensuite, vous incluez le fichier correspondant dans votre implémentation, le compilateur voit ce que vous voulez dire et tout le monde rentre chez lui à la barre. Ce qui s'est passé dans votre cas, je pense, est que le fichier d'implémentation pour le véhicule semble bien sur le papier, mais quelque chose d'autre comprend vehicle.h et il n'y a aucune idée de ce qu'est un Person.

Votre solution

Soit inclure person.h dans vehicle.h si vous devez, sinon changer ce constructeur de prendre une référence à personne (et membre), et avant de déclarer Person. Cependant, ne sachant pas ce que fait votre programme, je ne peux pas dire que même passer par référence est correct.

Et s'il vous plaît, retirez using namespace std; et changer vos string « s à std::string :)

+1

Il devrait l'inclure dans l'en-tête. Mais puisqu'il inclut "person.h" avant "vehicle.h" cela devrait fonctionner aussi. Ce n'est pas bien mais ça devrait marcher. Donc, savoir les messages d'erreur exacte serait bon. – mmmmmmmm

+0

Pourriez-vous expliquer un peu plus? Je mets une inclusion dans le fichier person.h dans le fichier vehicle.cpp, cela ne devrait-il pas suffire? – Pete

+0

@rstevens, j'ai attrapé cela mais je me demande s'il y a autre chose en jeu qui inclut vehicle.h. Pour le compilateur à barf, je peux seulement supposer qu'il est inclus ailleurs. –

1

Lorsque vous mettez un objet d'une autre classe dans votre classe, le compilateur a besoin de connaître la définition complète de cette classe. La meilleure façon de se souvenir de cette règle est de réaliser que vous ne pouvez pas connaître sizeof (Vehicle) tant que vous ne connaissez pas sizeof (Person), et que le compilateur ne le peut pas non plus. Les pointeurs et les références à une autre classe sont OK si vous faites d'abord une déclaration avant.

1

Est-ce que person.h contient la ligne #include "vehicle.h"? Les dépendances circulaires sont plus difficiles à gérer en C++ que par ex. Java ou C#. Vous pouvez facilement entrer dans une situation où vous avez besoin #include "Person.h" avant #include "Vehicle.h", mais vous avez également besoin #include "Vehicle.h" avant #include "Person.h".

Dans de nombreux cas, vous devez dire au compilateur "Person est le nom d'une classe, mais je ne suis pas encore prêt à vous donner la définition". Pour cela, vous pouvez dire class Person; Cela dénoue le problème de référence circulaire.

De même, faire beaucoup de copies d'un objet Person n'a probablement aucun sens, mais c'est ce que vous faites avec la valeur de transmission. On dirait que vous venez d'un environnement Java ou C#, où les variables de type classe sont automatiquement (et toujours) des références. En C++, vous devez demander une référence via Person* (un pointeur, peut être changé pour pointer vers une instance différente, comme les références Java et C#) ou Person& (une référence C++, attachée de façon permanente à une instance particulière).

+0

Ma personne n'a aucune inclusion à Vehicle.h. – Pete