Remarque: J'ai modifié mon ancienne question pour qu'elle soit aussi claire que possible.
J'ai une bibliothèque tierce nommée person.lib
Et son en-tête person.h
. Ceci est ma structure de projet réelle et elle se compile et fonctionne parfaitement.
main.cpp
#include <iostream>
#include <time.h>
#include <ctype.h>
#include <string>
#include "person.h"
using namespace person;
using namespace std;
class Client : public Person
{
public:
Client();
void onMessage(const char * const);
private:
void gen_random(char*, const int);
};
Client::Client() {
char str[11];
gen_random(str, 10);
this->setName(str);
}
void Client::onMessage(const char * const message) throw(Exception &)
{
cout << message << endl;
}
void Client::gen_random(char *s, const int len) {
//THIS FUNCTION GENERATES A RANDOM NAME WITH SPECIFIED LENGTH FOR THE CLIENT
}
int main()
{
try
{
Person *p = new Client;
p->sayHello();
}
catch(Exception &e)
{
cout << e.what() << endl;
return 1;
}
return 0;
}
Maintenant, je veux refactoriser mon code en divisant la déclaration de ma classe Client
de sa définition et créer client.h
Et client.cpp
. ATTENTION: sayHello()
et onMessage(const * char const)
sont des fonctions de la bibliothèque de personnes .
main.cpp
#include <iostream>
#include "client.h"
using namespace person;
using namespace std;
int main()
{
try
{
Person *p = new Client;
p->sayHello();
}
catch(Exception &e)
{
cout << e.what() << endl;
return 1;
}
return 0;
}
client.cpp
#include "client.h"
using namespace person;
using namespace std;
Client::Client() {
char str[11];
gen_random(str, 10);
this->setName(str);
}
void Client::onMessage(const char * const message) throw(Exception &)
{
cout << message << endl;
}
void Client::gen_random(char *s, const int len) {
//THIS FUNCTION GENERATES A RANDOM NAME WITH SPECIFIED LENGTH FOR THE CLIENT
}
client.h
#ifndef CLIENT_H
#define CLIENT_H
#include <time.h>
#include <ctype.h>
#include <string>
#include "person.h"
class Client : public Person
{
public:
Client();
void onMessage(const char * const);
private:
void gen_random(char*, const int);
};
#endif
Comme vous pouvez le voir, j'ai simplement créé un client.h
Dans lequel il y a l'inclusion de la classe de base person.h
, Puis j'ai créé client.cpp
Dans lequel il y a l'inclusion de client.h
Et les définitions de ses fonctions. Maintenant, la compilation me donne ces erreurs:
error C2504: 'Person': base class undefined client.h 7 1 Test
error C2440: 'inizialization': unable to convert from 'Client *' to 'person::impl::Person *' main.cpp 15 1 Test
error C2504: 'Person': base class undefined client.h 7 1 Test
error C2039: 'setName': is not a member of 'Client' client.cpp 8 1 Test
error C3861: 'sendMessage': identifier not found client.cpp 34 1 Test
C'est un refactoring simplement coupé et copié mais cela ne fonctionne pas et je ne comprends vraiment pas POURQUOI! Quelle est la solution et pourquoi cela me donne ces erreurs? Y a-t-il quelque chose sur la structure C++ qui me manque? Je vous remercie.
Voici une implémentation dog-n-bird (ruff ruff, cheep cheep) cLawyer est défini et implémenté dans main.cpp, tandis que cPerson et cClient sont définis dans leurs propres fichiers d'en-tête, implémentés dans leur propre fichier cpp. Une meilleure approche consisterait à stocker le nom de la classe. Ensuite, on n'aurait pas besoin de surcharger la méthode speak - on pourrait simplement définir le className dans chaque copie dérivée. Mais cela aurait fourni dans mes estimations, un exemple moins utile pour vous.
main.cpp
#include <cstdio>
#include "cClient.h"
class cLawyer : public cPerson
{
public:
cLawyer() : cPerson() {}
~cLawyer() {}
void talk(char *sayWhat){printf("cLawyer says: '%s'\n", sayWhat);}
};
int main()
{
cPerson newPerson;
cClient newClient;
cLawyer newLawyer;
newPerson.talk("Hello world!");
newClient.talk("Hello world!");
newLawyer.talk("Hello $$$");
return 0;
}
cPerson.h
#ifndef cPerson_h_
#define cPerson_h_
class cPerson
{
public:
cPerson();
virtual ~cPerson();
virtual void talk(char *sayWhat);
protected:
private:
};
#endif // cPerson_h_
cPerson.cpp
#include "cPerson.h"
#include <cstdio>
cPerson::cPerson()
{
//ctor
}
cPerson::~cPerson()
{
//dtor
}
void cPerson::talk(char *sayWhat)
{
printf("cPerson says: '%s'\n",sayWhat);
}
cClient.h
#ifndef cClient_h_
#define cClient_h_
#include "cPerson.h"
class cClient : public cPerson
{
public:
cClient();
virtual ~cClient();
void talk(char *sayWhat);
protected:
private:
};
#endif // cClient_h_
cClient.cpp
#include "cClient.h"
#include <cstdio>
cClient::cClient()
{
//ctor
}
cClient::~cClient()
{
//dtor
}
Sortie
cPerson says: 'Hello world!'
cClient says: 'Hello world!'
cLawyer says: 'Hello $$$'
Suggestions notées ci-dessus:
//In the cPerson class, a var
char *m_className;
//In the cPerson::cPerson constructer, set the var
m_className = "cPerson";
//Re-jig the cPerson::speak method
void cPerson::speak(char *sayWhat)
{
printf("%s says: '%s'\n", m_className, sayWhat);
}
// EDIT: *** remove the speak methods from the cClient and cLawyer classes ***
//Initialize the clas name apporpriately in derived classes
//cClient::cClient
m_className = "cClient";
//Initialize the clas name apporpriately in derived classes
//cLaywer::cLaywer
m_className = "cLawyer";
Vous déclarez la classe Client deux fois - une fois dans le .h
fichier et une fois dans .cpp
. Il vous suffit de le déclarer dans le .h
fichier.Vous devez également mettre le using namespace person;
à la .h
fichier.
Si la classe Personne est dans la personne d'espace de noms, utilisez le person::Person
pour y accéder.
Le client.cpp
doit contenir uniquement des définitions!
Je pense que pour l'éditeur de liens, la classe Client définie dans client.h et la classe Client définie dans client.cpp sont des classes différentes, donc il ne peut pas trouver l'implémentation de Client :: Client (). Je souhaite supprimer la déclaration de classe Client du client.cpp et y laisser uniquement des définitions de fonctions:
// client.cpp
#include <time.h>
#include <ctype.h>
#include <string>
#include "client.h"
using namespace std;
Client::Client()
{
//DO STUFF
}
void Client::onMessage(const char * const message)
{
//DO STUFF
}
void Client::gen_random(char *s, const int len) {
//DO STUFF
}