Une déclaration multiple survient au moment du linkage, c'est à dire au moment ou les modules compilés sont recollés de sorte à former un exécutable. Le problème c'est que par le biais des #include, tu peux avoir compiler une même section de code dans deux modules différents. Du coup, à la fin, tu obtiens une déclaration multiple.
Exemple
a.hpp
void f(){
std::cout << "Je suis f :-)" << std::endl;
}
b.hpp
#include "a.hpp"
void g(){
f();
}
main.hpp
#include "a.hpp"
#include "b.hpp"
int main(){
f();
g();
}
Quand on compile voici ce qu'il se passe :
* a ne dépend de personne et a.o (le module a compilé) contient le code de f. Jusque là tout va bien.
* b inclue a.hpp donc recopie le code concerné, celui de f(). b.o contient donc les fonctions f et g
* enfin on compile main.hpp, et là blam, on a deux fois f de définie, une fois dans a.hpp et une fois dans b.hpp, d'où multidéfinition...
Comment éviter le problème ?
=> Protéger le module pour que le hpp ne soit inclu qu'une fois :
plop.hpp
#ifndef PLOP
#define PLOP
//... code de plop.hpp ...
#endif
Autre point important faire attention (en particulier si des fonctions sont implémentées dans le .hpp) aux multidéfinitions de fonction, ie les fonctions dont le code à été copilé pour plusieurs .o. Supposons que a.hpp et b.hpp soient désormais protégés.
* a.o contiendra le code de f
* b.o contiendra le code de f et de g
* au cours des include du main le protype de f et g ne seront inclus qu'une fois, donc là tout va bien, opn n'a pas de multidéfinition. Par contre à la phase de linkage, f sera définie dans a.o et b.o d'ou une multi définition (!= déclaration multiple).
Pour régler le problème, soit on implémente f et g respectivement dans a.cpp et b.cpp, soit on les laisse dans les .hpp en les précédant du mot clé inline. Attention comme son nom l'indique ce mot clé est plutôt reservé au fonctions courtes car concrètement le compilateur remplace toutes les occurences de f() et de g() directement par leur code source.
#ifndef A_HPP
#define A_HPP
inline void f(){
std::cout << "je suis une fonction inline" << std::endl;
}
#endif
Maintenant tu sais tout sur les déclarations (portotype) et définitions (code source) multiples ^^
Bonne chance