héritage c++

héritage c++ - C++ - Programmation

Marsh Posté le 28-08-2002 à 16:29:49    

class mother
{
  virtual void toto() = 0;
}
 
class A : public class mother
{
}
 
class MotherFils1 : public class mother
{
  void toto()  
  {
  }
}
 
class MotherFils2 : public class mother
{
  void toto()  
  {
  }
}
 
 
les classes "mother" et "A" sont abstraite.
 
j'aimerai instancier la classe "A" en spécifiant que sa classe mere est (au choix)"MotherFils1" (ou "MotherFils2" )
 
c'est possible ?
 
(j'espere que je suis pas trop flou  :pt1cable: )
 
merci

Reply

Marsh Posté le 28-08-2002 à 16:29:49   

Reply

Marsh Posté le 28-08-2002 à 16:31:42    

C pas possible


---------------
Le Tyran
Reply

Marsh Posté le 28-08-2002 à 16:33:33    

On peut pas instancier une classe abstraite.


---------------
J'ai un string dans l'array (Paris Hilton)
Reply

Marsh Posté le 28-08-2002 à 16:43:44    

ton choix devrait plutôt porter sur instancier un MotherFils1 ou un MotherFils2 ...

Reply

Marsh Posté le 28-08-2002 à 17:35:57    

en fait voila exactement ce que je voudrai faire :
 
class mother  
{  
 virtual void toto() = 0;  
};
 
class MotherFils1 : public virtual mother  
{  
 void toto()  
 {  
   printf("fils1\n" );
 }  
};
 
class MotherFils2 : public virtual mother  
{  
 void toto()  
 {  
   printf("fils2\n" );
 }  
};  
 
class A : public MotherFils1, public MotherFils2
{
 
};
 
int main(int argc, char* argv[])
{
  return 0;
}
 
 
A la compilation j'ai cette erreur :  
 
error C2250: 'A' : ambiguous inheritance of 'MotherFils1::toto'
error C2250: 'A' : ambiguous inheritance of 'MotherFils2::toto'
 
Ce que je voudrai c'est instancier "A" en spécifiant que "A" hérite de MotherFils1 (ou de MotherFils2 au choix)
 
Mais je crois, en effet, qu'il n'y a pas de solution possible ... à moins que qq1 ai une suggestion ...

Reply

Marsh Posté le 28-08-2002 à 17:43:22    

Code :
  1. class A : public MotherFils1, public MotherFils2
  2. {
  3. };


 
 
La A hérite de MotherFils1 et de MotherFils2.
 
Si tu veus aucun pb il faut faire:

Code :
  1. class Mother
  2. {
  3. }
  4. class MotherFils1 : public virtual Mother
  5. {
  6. }
  7. class MotherFils2 : public virtual Mother
  8. {
  9. }
  10. class A : public virtual MotherFils1, public virtual MotherFils2
  11. {
  12. };


---------------
Le Tyran
Reply

Marsh Posté le 28-08-2002 à 17:44:34    

Suivant quel 'choix' ?

Reply

Marsh Posté le 28-08-2002 à 17:55:35    

indice a écrit a écrit :

 
 
Ce que je voudrai c'est instancier "A" en spécifiant que "A" hérite de MotherFils1 (ou de MotherFils2 au choix)
 
Mais je crois, en effet, qu'il n'y a pas de solution possible ... à moins que qq1 ai une suggestion ...
 




 
???????  :??:  
 
Visiblement, Bjarne n'a pas conçu le C++ selon ta méthode de pensée  :pt1cable:  
 
Tu veux faire quoi EXACTEMENT ?  Une classe hérite d'une ou plusieurs classes mais c'est pas "au choix" (encore heureux, ça servirait à rien et ça serait inutilisable)
 
T'es sûr que tu n'es pas en train de vouloir réinventer le polymorphisme ?
 
Peut être veux tu simplement instancier une collection en vrac d'instances de MotherFils1 et de MotherFils2 et de pouvoir les utiliser indifféremment ? Si c'est le cas, la classe A ne sert à rien.

Reply

Marsh Posté le 28-08-2002 à 17:59:03    

letoII a écrit a écrit :

Code :
  1. class A : public MotherFils1, public MotherFils2
  2. {
  3. };


 
 
La A hérite de MotherFils1 et de MotherFils2.
 
Si tu veus aucun pb il faut faire:

Code :
  1. class Mother
  2. {
  3. }
  4. class MotherFils1 : public virtual Mother
  5. {
  6. void toto() 
  7. {
  8.   printf("fils1\n" );
  9. }
  10. }
  11. class MotherFils2 : public virtual Mother
  12. {
  13. void toto() 
  14. {
  15.   printf("fils2\n" );
  16. }
  17. }
  18. class A : public virtual MotherFils1, public virtual MotherFils2
  19. {
  20. };






 
ok, mais le pb lors de l'instanciation :
 
A a;
a.toto();  // <- ici "a" ne sais pas s'il faut appeler MotherFils1::toto() ou MotherFils2::toto()
 
 
En fait ce que je voudrai c'est avoir une classe mere "virtuelle" : c'est a dire avoir une classe mere qui peut changer au runtime. (en sachant que cette classe mere hérite elle meme d'une autre classe mere, sinon ca serai impossible à gérer pour le compilo).
 
Mais la je suis sur que c pas possible  
en tout cas merci pour vos réponse ...

Reply

Marsh Posté le 28-08-2002 à 18:00:56    

indice a écrit a écrit :

 
 
En fait ce que je voudrai c'est avoir une classe mere "virtuelle" : c'est a dire avoir une classe mere qui peut changer au runtime. (en sachant que cette classe mere hérite elle meme d'une autre classe mere, sinon ca serai impossible à gérer pour le compilo).




 
Pas possible l'héritage dynamique (c bien ça le terme?)


---------------
Le Tyran
Reply

Marsh Posté le 28-08-2002 à 18:00:56   

Reply

Marsh Posté le 28-08-2002 à 18:11:23    

indice a écrit a écrit :

 
 
ok, mais le pb lors de l'instanciation :
 
A a;
a.toto();  // <- ici "a" ne sais pas s'il faut appeler MotherFils1::toto() ou MotherFils2::toto()
 
 
En fait ce que je voudrai c'est avoir une classe mere "virtuelle" : c'est a dire avoir une classe mere qui peut changer au runtime. (en sachant que cette classe mere hérite elle meme d'une autre classe mere, sinon ca serai impossible à gérer pour le compilo).




 
Je crois qu'il faudrait que tu lises au moins un bouquin sur les méthodes de la conception objet avant de commencer à créer des hierarchies inutilement compliquées...

Reply

Marsh Posté le 28-08-2002 à 18:12:41    

Smaragdus a écrit a écrit :

 
 
???????  :??:  
 
Visiblement, Bjarne n'a pas conçu le C++ selon ta méthode de pensée  :pt1cable:  
 
Tu veux faire quoi EXACTEMENT ?  Une classe hérite d'une ou plusieurs classes mais c'est pas "au choix" (encore heureux, ça servirait à rien et ça serait inutilisable)
 
T'es sûr que tu n'es pas en train de vouloir réinventer le polymorphisme ?
 
Peut être veux tu simplement instancier une collection en vrac d'instances de MotherFils1 et de MotherFils2 et de pouvoir les utiliser indifféremment ? Si c'est le cas, la classe A ne sert à rien.




 
voila un exemple concret :
 
class objet3D //represente un objet en 3D que l'on peut deplacer
{
   virtual dessinerObjet() = 0; //permet de dessiner l'objet
}
 
class velo : public objet3D //represente un velo
{
}
 
class objet3DpourCarteATI : public objet3D
{
  dessinerObjet()
  {
    on dessine l'objet avec les fcction d'ATI
  }
}
 
class objet3DpourCarteNVIDIA : public objet3D
{
  dessinerObjet()
  {
    on dessine l'objet avec les fcction de nvdia
  }
}
 
 
main()
{
  Velo *v;
  if(on_a_une_ATI)
  {
    v = new Velo; // et la je voudai dire que la class de base est objet3DpourCarteATI  
  }
  else
  {
    v = new Velo; // et la je voudai dire que la class de base est objet3DpourCarteNVIDIA  
  }  
}
 
et en effet j'ai l'impression de faire de la POO a ma maniere ...
 
mais bon, techniquement ca me semblai faisable, je pensai qu'il y avait une solution .....

Reply

Marsh Posté le 28-08-2002 à 18:21:58    

indice a écrit a écrit :

 
 
voila un exemple concret :
 
class objet3D //represente un objet en 3D que l'on peut deplacer
{
   virtual dessinerObjet() = 0; //permet de dessiner l'objet
}
 
class velo : public objet3D //represente un velo
{
}
 
class objet3DpourCarteATI : public objet3D
{
  dessinerObjet()
  {
    on dessine l'objet avec les fcction d'ATI
  }
}
 
class objet3DpourCarteNVIDIA : public objet3D
{
  dessinerObjet()
  {
    on dessine l'objet avec les fcction de nvdia
  }
}
 
 
main()
{
  Velo *v;
  if(on_a_une_ATI)
  {
    v = new Velo; // et la je voudai dire que la class de base est objet3DpourCarteATI  
  }
  else
  {
    v = new Velo; // et la je voudai dire que la class de base est objet3DpourCarteNVIDIA  
  }  
}
 
et en effet j'ai l'impression de faire de la POO a ma maniere ...
 
mais bon, techniquement ca me semblai faisable, je pensai qu'il y avait une solution .....




 
C'est incohérent ce que tu veux faire : tu vas pas tester la vérification de la CG à chaque fois que tu instancies ton objet  :pt1cable: Ou alors tu fais 2 classes VeloATI et VeloNvidia. Ou alors tu fais un template avec lequelle tu choisis une classes par carte. Il y a pleins de méthodes pour resoudre ça.
 
De plus, je vois pas comment objet3DpourCarteNvidia saurait quoi dessiner puisque l'implémentation du dessin s'effectuera dans les descendants.

Reply

Marsh Posté le 28-08-2002 à 18:23:34    

Fait plutot une classe abstraite Renderer, avec deux sous classes RendererNVidia et RendererATI. Dans Renderer, définie une méthode draw (const Objet3D *), qui doit être surchargée dans les sous classes.
 
Au final, ton main devient :  
 

Code :
  1. main()
  2. {
  3. Velo *v = new Velo;
  4. Renderer * renderer;
  5. if(on_a_une_ATI)
  6. {
  7.     renderer = newRendererNATI;
  8. }
  9. else
  10. {
  11.     renderer = newRendererNVidia;
  12. renderer->draw (v);
  13. }


Message édité par kadreg le 28-08-2002 à 18:26:39

---------------
brisez les rêves des gens, il en restera toujours quelque chose...  -- laissez moi troller sur discu !
Reply

Marsh Posté le 28-08-2002 à 18:31:06    

Smaragdus a écrit a écrit :

 
 
C'est incohérent ce que tu veux faire : tu vas pas tester la vérification de la CG à chaque fois que tu instancies ton objet  :pt1cable:  




 l'objet est instancié une fois pour toute au debut ....
[citation]
Ou alors tu fais 2 classes VeloATI et VeloNvidia. Ou alors tu fais un template avec lequelle tu choisis une classes par carte. Il y a pleins de méthodes pour resoudre ça.
[/citation]
 
Le pb avec cette méthode c'est que si je veux creer une classe de type voiture, je suis obligé de créer voitureATI et voitureNvidia, (alors que si ma méthode avait été possible j'avais juste à creer une class voiture)
 
[citation]
De plus, je vois pas comment objet3DpourCarteNvidia saurait quoi dessiner puisque l'implémentation du dessin s'effectuera dans les descendants.
[/citation]
 
"l'implementation du dessin" justement ce trouve dans objet3DpourCarteNvidia::dessinerObjet()
et cette methode est appelé de cette maniere objet3d::dessinerObjet()
 
en tout cas mer6 pour tes réponses

Reply

Marsh Posté le 28-08-2002 à 18:35:05    

indice a écrit a écrit :

 
 
 
"l'implementation du dessin" justement ce trouve dans objet3DpourCarteNvidia::dessinerObjet()
et cette methode est appelé de cette maniere objet3d::dessinerObjet()
 




 
C'est bien ce que je disais, c'est incohérent puisque si le dessin est dans objet3DpourCarteNvidia:: dessinerObjet(), Velo:: dessinerObjet() sert à quoi ? :D


Message édité par smaragdus le 28-08-2002 à 18:35:35
Reply

Marsh Posté le 28-08-2002 à 18:43:10    

Smaragdus a écrit a écrit :

 
 
C'est bien ce que je disais, c'est incohérent puisque si le dessin est dans objet3DpourCarteNvidia:: dessinerObjet(), Velo:: dessinerObjet() sert à quoi ? :D




 
Velo:: dessinerObjet() n'existe parce que Velo ne contient pas les donnée 3D (triangles etc ...)
C'est justement objet3D qui contient ces données
et qd j'appel la méthode objet3D::dessinerObjet c'est l'objet objet3DpourCarteNvidia qui dessiner les triangles a partir des données contenu dans objet3D (sa classe mere)

Reply

Marsh Posté le 28-08-2002 à 20:40:37    

tu veux pouvoir choisir à l'instanciation de dériver de fils1 ou fils2...utilise les templates!
 
template <class I>
class interface: public I
{
 
}
 
class CPere
{
  //que des méthodes virtuelles (mais pas virtuelles pur) rédéfinies dans Fils1 et Fils2)
}
 
class CFils1 : public CPere, public interface<CMotherFils1>
{
 
}
 
class CFils2 : public CPere, public interface<CMotherFils2>
{
 
}
 
évidemment MotherFils2/1 dérive de Mother
 
voici le schéma correspondant :
 
         Mother
           |
           |
      MotherFils1/2
           |
           |
  interface  Pere
           |
           |
         Fils1/2
 
A l'instanciation :
 
CPere* fils[2];
 
fils[0]=new CFils1();
fils[1]=new CFils2();
 
 
jamais testé mais ça devrait marcher, (c'est possible que l'héritage multiple ne soit pas supporté pour les classes dérivant déjà d'une classe templates...à vérifier)


Message édité par weblook$ le 28-08-2002 à 20:48:15
Reply

Marsh Posté le 30-08-2002 à 03:04:04    

Ça peut se faire comme ça:

Code :
  1. enum cards {ATI, nVidia};
  2. class objet3D{public:
  3. virtual void dessinerObjet()= 0;
  4. };
  5. class objet3DATI    : public objet3D{
  6. void dessinerObjet(){cout<<"ATI\n";}
  7. };
  8. class objet3DnVidia : public objet3D{
  9. void  dessinerObjet(){cout<<"nVidia\n";}
  10. };
  11. class velobase{} ;
  12. template <class T>
  13. class velo : public velobase, public T{} ;
  14. main(){
  15. objet3D *v;
  16. cards card= ATI;
  17. switch(card){
  18.  case ATI   : v= new velo<objet3DATI   >; break;
  19.  case nVidia: v= new velo<objet3DnVidia>; break;
  20.  default: ;//Inconnue
  21. }
  22. v->dessinerObjet(); //ATI ou nVidia
  23. return 0;
  24. }

Mais je suis d'accord avec tout le monde que c'est pas une bonne approche.
 
Je pense plutôt à ça:

Code :
  1. class objet3D{
  2. public:
  3. char aspect ;
  4. virtual void dessiner()= 0;
  5. };
  6. enum cards {ATI, nVidia};
  7. class card3D{
  8. public:
  9. virtual void render(objet3D&)= 0;
  10. };
  11. card3D* card;
  12. class card3DATI   : public card3D{
  13. void render(objet3D& o){cout<< "ATI    affiche:"<<o.aspect<<endl; };
  14. };
  15. class card3DnVidia: public card3D{
  16. void render(objet3D& o){cout<< "nVidia affiche:"<<o.aspect<<endl; };
  17. };
  18. class velo3D : public objet3D{
  19. public:
  20. velo3D(){
  21.  aspect= 'V';
  22. }
  23. void dessiner(){card->render(*this);}
  24. };
  25. int main(){
  26. switch(ATI){
  27.  case ATI   : card= new card3DATI   ; break;
  28.  case nVidia: card= new card3DnVidia; break;
  29.  default: ;//Inconnue
  30. }
  31. velo3D v;
  32. v.dessiner();
  33. return 0;
  34. }

Mais c'est pas terrible non plus.
 
render pourrait être tout simplement un pointeur de fonction.


Message édité par Musaran le 30-08-2002 à 03:04:42

---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 30-08-2002 à 10:22:44    

bon la je suis dans le pate donc si je radote fo pas m'en vouloir.
 
le truc a faire :
 

Code :
  1. class Renderer
  2. {
  3. public:
  4.   virtual init() = 0;
  5.   virtual deinit() = 0;
  6. protected:
  7.   virtual draw( Objet3D* obj ) = 0;
  8. };
  9. class ATIRenderer : public Renderer
  10. {
  11. public:
  12.   virtual init();
  13.   virtual draw( Objet3D* obj ); // dessin via ATI
  14.   virtual deinit();
  15. };
  16. class NVIDIARenderer : public Renderer
  17. {
  18. public:
  19.   virtual init();
  20.   virtual draw( Objet3D* obj ); // dessin via NVIDIA
  21.   virtual deinit();
  22. };
  23. class Objet3D
  24. {
  25.   public:
  26.     virtual dessine() = 0;
  27.   private:
  28.     Renderer* renderInterface;
  29. };
  30. class Velo3D : public Objet3D
  31. {
  32.   public:
  33.     virtual dessine()
  34.     {
  35.         renderInterface->dessine( this );
  36.     }
  37.     Velo3D( Renderer* interface ) : renderInterface( interfac )
  38. };
  39. int main()
  40. {
  41.    Renderer* interface;
  42.    switch( VIDEOCARDTYPE )
  43.    {
  44.      case ATI    : interface = new ATIRenderer; break;
  45.      case NVIDIA : interface = new NVIDIARendere; break;
  46.      default : cout << "Achete toi une carte 3D banane !!" <<endl; break;
  47.    }
  48.     Velo3D festina( interface );
  49.     interface->init();
  50.     festina->dessine();
  51.     interface->deinit();
  52. }


 
Voila au erreurs de claviers pres.
C'est + propre non ??
De toute maniére tu va etre obligé de tester le type de carte avant d'instancier les trucs ...

Reply

Marsh Posté le 30-08-2002 à 10:25:39    

Joel F a écrit a écrit :

bon la je suis dans le pate donc si je radote fo pas m'en vouloir.
 
le truc a faire :
 

Code :
  1. class Renderer
  2. {
  3. public:
  4.   virtual init() = 0;
  5.   virtual deinit() = 0;
  6. protected:
  7.   virtual draw( Objet3D* obj ) = 0;
  8. };
  9. class ATIRenderer : public Renderer
  10. {
  11. public:
  12.   virtual init();
  13.   virtual draw( Objet3D* obj ); // dessin via ATI
  14.   virtual deinit();
  15. };
  16. class NVIDIARenderer : public Renderer
  17. {
  18. public:
  19.   virtual init();
  20.   virtual draw( Objet3D* obj ); // dessin via NVIDIA
  21.   virtual deinit();
  22. };
  23. class Objet3D
  24. {
  25.   public:
  26.     virtual dessine() = 0;
  27.   private:
  28.     Renderer* renderInterface;
  29. };
  30. class Velo3D : public Objet3D
  31. {
  32.   public:
  33.     virtual dessine()
  34.     {
  35.         renderInterface->dessine( this );
  36.     }
  37.     Velo3D( Renderer* interface ) : renderInterface( interfac )
  38. };
  39. int main()
  40. {
  41.    Renderer* interface;
  42.    switch( VIDEOCARDTYPE )
  43.    {
  44.      case ATI    : interface = new ATIRenderer; break;
  45.      case NVIDIA : interface = new NVIDIARendere; break;
  46.      default : cout << "Achete toi une carte 3D banane !!" <<endl; break;
  47.    }
  48.     Velo3D festina( interface );
  49.     interface->init();
  50.     festina->dessine();
  51.     interface->deinit();
  52. }


 
Voila au erreurs de claviers pres.
C'est + propre non ??
De toute maniére tu va etre obligé de tester le type de carte avant d'instancier les trucs ...




 
M'excuse apr avance pour le petit pourrissage de topic: J'avais po vu la signature  :lol:


---------------
Le Tyran
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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