Inclusion circulaire & quelques questions

Inclusion circulaire & quelques questions - C++ - Programmation

Marsh Posté le 11-01-2013 à 14:25:03    

Bonjour cher amis codeurs !
 
Je rencontre quelques soucis depuis un certain temps, et je me suis dit que ça serais bien de les résoudre...
 
1/
 
Idée : Un objet Device est contrôlé par plusieurs "modules", dont le NetworkController.
Device doit pouvoir accèder au NetworkController pour l'initialiser, le stopper, ... (ici, j'ai juste écrit l'initialisation)
NetworkController doit pouvoir accèder au Device pour lui dire de faire tel ou tel truc (ici juste la fonction Bip() )
le problème vient de l'inclusion : je ne sais pas comment la tourner pour que l'une ne gène pas l'autre.
 
Voici le petit programme minimal qui ne compile pas :
 
main.cpp

Code :
  1. #include "Device.hpp"
  2. int main()
  3. {
  4. Device dev;
  5. return 0;
  6. }


 
Device.cpp

Code :
  1. #ifndef INC_DEVICE
  2. #define INC_DEVICE
  3. #include <stdio.h>
  4. #include "NetworkCtrl.hpp"
  5. class Device
  6. {
  7. public:
  8. //Init the device & network controller
  9.     Device() : m_ctrl(this){}
  10.    
  11.     void Bip(){printf("\a" );}
  12. private:
  13.     NetworkCtrl m_ctrl;
  14. };
  15. #endif


 
NetworkCtrl.hpp

Code :
  1. #ifndef INC_NETCTRL
  2. #define INC_NETCTRL
  3. #include "Device.hpp"
  4. //Network controller
  5. class NetworkCtrl
  6. {
  7. public:
  8.     NetworkCtrl(Device* dev)
  9.     {
  10.         m_dev = dev;
  11.     }
  12.    
  13.     //Example function, called in a seperated thread
  14.     void ExampleFunction()
  15.     {
  16.         m_dev->Bip();
  17.     }
  18. private:
  19.     Device* m_dev;
  20. };
  21. #endif


 
Voir "dépendance circulaire"
http://stackoverflow.com/questions [...] lationship
Merci gelatine_velue & dwogsi
 
2/
 
Cette fois c'est plus simple :p
Comment définir une variable statique dans un header, et l'utiliser dans le même fichier ?
En gros je suis un peu fainéant, et je ne veut pas utiliser de .cpp et tout mettre dans le .h
 
Exemple:
Device.hpp

Code :
  1. class Device
  2. {
  3. public:
  4.     Device(){m_instance = this;}
  5.     static Device* GetInstance()
  6.     {
  7.         return m_instance;
  8.     }
  9. private:
  10.     static Device* m_instance;
  11. }


 
 
3/
 
Est il possible de stocker le type d'une variable dans une autre?
Par exemple j'ai un objet Sac, qui contient une variable "vector<Objet*> m_obj"
Dans la classe Objet, il y aurait une variable "xxxx m_type" qui serait initialisée dans les classes filles, avec le type de la classe fille.
Cela me permettrais ensuite de faire : dynamic_cast<m_obj[0].m_type> m_obj[0]
 
Pour l'instant je me contente d'un "int m_type", et de switch/case pour caster correctement les objets, mais c'est pas très pratique niveau évolutivité...
 
Merci d'avance pour votre aide ! :)


Message édité par crom29 le 11-01-2013 à 14:58:46

---------------
Mods: HAF922 | Shinobi XL White    GitHub     Admin de La Colère d'Aurile, serveur RP-Action Neverwinter Nights 2
Reply

Marsh Posté le 11-01-2013 à 14:25:03   

Reply

Marsh Posté le 11-01-2013 à 14:46:54    

1/ Tu dois utliser ce que l'on appelle forward declaration

 

Ex. copié de http://stackoverflow.com/questions [...] lationship

 
Code :
  1. //parent.h
  2. class Child; //Forward declaration
  3. class Parent
  4. {
  5.     vector<Child*> m_children;
  6. };
  7. //child.h
  8. class Parent; //Forward declaration
  9. class Child
  10. {
  11.     Parent* m_parent;
  12. };
 

2/ Tu peux donner un cas le plus court possible qui ne marche pas?


Message édité par gelatine_velue le 11-01-2013 à 14:48:02
Reply

Marsh Posté le 11-01-2013 à 14:49:14    

Pour infos, c'est ce qu'on appel une dépendance circulaire.
Ça peut aider pour de futures recherches :)


---------------
-- Debian -- Le système d'exploitation universel | Le gras c'est la vie! | /(bb|[^b]{2})/
Reply

Marsh Posté le 11-01-2013 à 14:54:11    

Merci beaucoup de vos réponses !
 
J'ai rajouté un 3e point :p
 
 
Exemple pour la variable statique dans le header:
Device.hpp

Code :
  1. class Device
  2. {
  3. public:
  4.     Device(){m_instance = this;}
  5.     static Device* GetInstance()
  6.     {
  7.         return m_instance;
  8.     }
  9. private:
  10.     static Device* m_instance;
  11. }


Note : j'ai pas testé à l'instant, mais je me souviens très bien que ce code ne compilait pas


---------------
Mods: HAF922 | Shinobi XL White    GitHub     Admin de La Colère d'Aurile, serveur RP-Action Neverwinter Nights 2
Reply

Marsh Posté le 11-01-2013 à 15:06:46    

crom29 a écrit :

Merci beaucoup de vos réponses !
 
J'ai rajouté un 3e point :p
 
 
Exemple pour la variable statique dans le header:
Device.hpp

Code :
  1. class Device
  2. {
  3. public:
  4.     Device(){m_instance = this;}
  5.     static Device* GetInstance()
  6.     {
  7.         return m_instance;
  8.     }
  9. private:
  10.     static Device* m_instance;
  11. };


Note : j'ai pas testé à l'instant, mais je me souviens très bien que ce code ne compilait pas


 
T'as oublié un ; à la fin de la décalration de la classe. Sinon ça compile.

Reply

Marsh Posté le 11-01-2013 à 15:24:09    

chez moi ça compile pas
Voici mon fichier:
main.cpp

Code :
  1. class Device
  2. {
  3. public:
  4.     Device(){m_instance = this;}
  5.     static Device* GetInstance()
  6.     {
  7.         return m_instance;
  8.     }
  9. private:
  10.     static Device* m_instance;
  11. };
  12. int main()
  13. {
  14.     Device dev1;
  15.     return 0;
  16. }
 

(si tu n'instancie pas la classe, ça compile)


Message édité par crom29 le 11-01-2013 à 15:25:04

---------------
Mods: HAF922 | Shinobi XL White    GitHub     Admin de La Colère d'Aurile, serveur RP-Action Neverwinter Nights 2
Reply

Marsh Posté le 11-01-2013 à 15:38:09    

En effet. Je suis pas assez colé en C++ pour te répondre. Par contre, c'est pas comme ça qu'on fait un singleton, si tu essaies de faire ça.

Reply

Marsh Posté le 11-01-2013 à 16:00:25    

Disons que c'est un singleton vite fait sans sécurités contre la double instanciation et sans auto-instanciation :p


---------------
Mods: HAF922 | Shinobi XL White    GitHub     Admin de La Colère d'Aurile, serveur RP-Action Neverwinter Nights 2
Reply

Marsh Posté le 11-01-2013 à 16:08:10    

Soyons précis, cela compile, mais cela ne linke pas :)
Dans l'exemple que vous donnez, vous déclarez une variable globale (car un attribut de classe revient à ça), mais vous ne la définissez pas.
 
Il suffit, dans votre cas, de rajouter après la déclaration de la classe Device la ligne  
 

Code :
  1. Device* Device::m_instance;


 
ou, si vous désirez l'intialiser
 

Code :
  1. Device* Device::m_instance = NULL;


 
Si vous aviez un Device.cpp, cela aurait été le bon endroit pour mettre cette déclaration, sinon, il faut la placer à un endroit unique (donc pas dans le fichier Device.h (ou alors en assurant l'unicité de la déclaration via des primitives de précompilation, mais cela n'est pas forcément utile de compliquer l'affaire ...)
 
Comme indiqué plus haut, faites comme si vous aviez une variable globale que vous déclareriez en extern dans un fichier .h, c'est exactement la même chose (à la visibilité près, du au fait que l'attribut de classe est privé, bien sûr ! :) )
 
Pour le 3e point, je dirais que non, pas à ma connaissance, le mieux serait de passer par des classes templates.
 
Bonne continuation !

Reply

Marsh Posté le 11-01-2013 à 16:11:11    

Merci beaucoup Farian :)

 

Autant pour moi, mes yeux ont décidés de ne pas voir "error: ld returned 1" ^^
Tous vos conseils vont me permettre de simplifier pas mal mon code ! Encore Merci :)


Message édité par crom29 le 11-01-2013 à 16:15:26

---------------
Mods: HAF922 | Shinobi XL White    GitHub     Admin de La Colère d'Aurile, serveur RP-Action Neverwinter Nights 2
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed