Questions diverses de débutant

Questions diverses de débutant - C++ - Programmation

Marsh Posté le 10-03-2006 à 12:40:55    

Bonjour,  
Je fais du C depuis quelques temps et j'essaie d'apprendre le C++. J'aurais quelques questions concernant les notions d'objet en particulier.
Tout d’abord je voulais avoir ce qu’est une classe virtuelle, quand doit-on l’utiliser et pourquoi ?  
D’autre part, je ne comprends pas ce qu’est l’opérateur « dynamic-cast » et la manière dont
on l’utilise (je sais uniquement qu’il réalise des changements de type mais je ne vois pas l’intérêt) ?  
Je ne vois pas non plus c’est qu’est polymorphisme, son intérêt et pourquoi il n’est possible que sur des pointeurs objets ? Enfin je me demandais si une classe abstraite pouvait être instanciée et pourquoi ?
 
 
Merci à tous ceux qui pourront éclairer ma lanterne.

Reply

Marsh Posté le 10-03-2006 à 12:40:55   

Reply

Marsh Posté le 10-03-2006 à 14:25:58    

ça n'existe pas le concept de classe virtuelle. par contre base abstraite ou fonction membre virtuelle ...
 
tu ne vois pas l'intérêt du polymorphisme ? alors va lire ton cours ou bien wikipedia.
le polymorphisme en C++ est mis en oeuvre sur les pointeurs et les références.
 
et ta dernière instance sur la classe abstraite, meme réponse : va lire ton cours ou wikipedia.
 
Si tu veux nous demander d'autres choses genre 'pourquoi un carré n'est pas rond', te gène pas.

Reply

Marsh Posté le 10-03-2006 à 15:25:44    

pourquoi un carré n'est pas rond ?


---------------
http://www.blastmanu.info
Reply

Marsh Posté le 10-03-2006 à 22:13:51    

Une fonction polymorphe ou virtuelle est une methode qui est appelé en fonction du type d'objet et non pas en fonction du type du pointeur utilisé.
 
L'opérateur dynamic_cast permet de convertir un pointeur d'une classe de base vers un pointeur d'une classe dérivé, la classe de base doit obligatoirement pooséder au moin une fonction virtuelle.
 
Exemple de fonction virtuelle :
 
class M
{
  public void affiche()
  {
  cout << "base";
  }
};
 
class N : public M
{
  public void affiche()
  {
  cout << "fille";
  }
};
 
M * p1 = new M;  
p1.affiche;    // Resultat "base"
M * p2 = new N;
p2.affiche    // Resultat "base" !!!!
 
Dans ce cas le pointeur p2 est de type M donc il va chercer M::affiche alors que si M::affiche était virtuelle p2 aurait pointé vers N::affiche
 
J'espere mettre fais comprendre, le principe n'est pas compliqué c'est juste le coté novateur.

Message cité 1 fois
Message édité par Profil supprimé le 10-03-2006 à 22:23:00
Reply

Marsh Posté le 10-03-2006 à 22:59:28    


 
 
Je comprend l'interet d'une methode virtuel dans le cas d'une specialisation mais là je ne vois pas l'interêt d'instancier une classe fille pour appeler des methodes de la classe mere qui ont du être hérité de toute manière.

Reply

Marsh Posté le 10-03-2006 à 23:20:12    


Allez! Une petite histoire:
 

Code :
  1. #include <stdio.h>
  2. class EtreVivant
  3. {
  4.   public:
  5.   virtual void parle()=0;
  6. };
  7. class Homme: public EtreVivant
  8. {
  9.   public:
  10. };
  11. class Noe: public Homme
  12. {
  13.   public:
  14.   void parle()
  15.   { printf("Passeport, svp?\n" ); }
  16. };
  17. class Animal: public EtreVivant
  18. {
  19.   public:
  20. };
  21. class Chien: public Animal
  22. {
  23.   public:
  24.   void parle()
  25.   { printf("Ouaf! Ouaf!\n" ); }
  26. };
  27. class Chat: public Animal
  28. {
  29.   public:
  30.   void parle()
  31.   { printf("Miaou! Miaou!\n" ); }
  32. };
  33. class Poule: public Animal
  34. {
  35.   public:
  36.   void parle()
  37.   { printf("Cot! Cot! Cot!\n" ); }
  38. };
  39. class Arche
  40. {
  41.   Homme* homme;
  42.   public:
  43.   Arche(Homme* commandant):
  44.     homme(commandant)
  45.   {}
  46.   void abriter(Animal* animal)
  47.   {
  48.     homme->parle();
  49.     animal->parle();
  50.   }
  51. };
  52. int main()
  53. {
  54.   Noe* noe=new Noe();
  55.   Arche* arche=new Arche(noe);
  56.   arche->abriter(new Chien());
  57.   arche->abriter(new Chat());
  58.   arche->abriter(new Chien());
  59.   return 0;
  60. }


Reply

Marsh Posté le 10-03-2006 à 23:20:52    

classe mère : A
classe fille : B
 
B est un A, donc les opérations sur un A s'applique à un B.

Reply

Marsh Posté le 11-03-2006 à 00:05:52    

blastman a écrit :

pourquoi un carré n'est pas rond ?


Un cercle peut-être carré tout dépend de la définition de la distance que tu prends  :lol:

Reply

Marsh Posté le 11-03-2006 à 00:16:14    

en topologie, une boule, ça peut ressembler visuellement à un carré. Et en POO, une boule n'est pas un carré, et un rectangle non plus :)

Reply

Marsh Posté le 11-03-2006 à 07:55:37    

++fab a écrit :

en topologie, une boule, ça peut ressembler visuellement à un carré. Et en POO, une boule n'est pas un carré, et un rectangle non plus :)

Ça fout les boules [:m@nou]

Reply

Marsh Posté le 11-03-2006 à 07:55:37   

Reply

Marsh Posté le 11-03-2006 à 10:29:40    

++fab a écrit :

en topologie, une boule, ça peut ressembler visuellement à un carré. Et en POO, une boule n'est pas un carré, et un rectangle non plus :)


 
Parcontre ils héritent tous les 3 de "formeGeometrique" , parcontre boule herite de figure3D alros que les 2 autres de figure2D
Ensuite carré est juste un enfant de rectangle
, bref je m'égare

Message cité 1 fois
Message édité par esox_ch le 11-03-2006 à 10:30:55

---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait
Reply

Marsh Posté le 11-03-2006 à 10:33:44    

un carré est hérite également de losange

Reply

Marsh Posté le 11-03-2006 à 10:36:58    

esox_ch a écrit :

Ensuite carré est juste un enfant de rectangle


 

Citation :

un carré est hérite également de losange


 
Non, et non. En tout cas pas via un héritage public.

Reply

Marsh Posté le 11-03-2006 à 10:44:00    

tu peux expliquer ?

Reply

Marsh Posté le 11-03-2006 à 11:33:48    

skelter a écrit :

tu peux expliquer ?


C'est l'exemple classique que d'autres expliquent beaucoup mieux que moi ...
Je peux te donner des références sur le sujet :
- Effective C++ Item 32
- Un des  * exceptional * C++, je ne sais plus lequel, ni l'item.
- Barton & Nackman Ch. 10
 
Ce qu'il faut retenir c'est : ne jamais hériter publiquement d'une classe concrète. C'est parfois contradictoire avec l'observation, mais -- dans le langage C++ -- hériter publiquement d'une classe concrète amène à moults incohérences, impasses, maladresses, exposition de l'implémentation, ...
 
Dans un beau design OO C++-ien, t'as souvent une base abstraite, qui contient des fonctions publiques non-virtuelles, qui appellent des fonctions privées/protégées virtuelles. Les classes filles supplantent les fonctions virtuelles à leur guise, et entre elles, factorisent leurs propriétés communes par le biais d'héritage privé, d'héritage protégé, de composition, d'héritage multiple.

Reply

Marsh Posté le 11-03-2006 à 12:03:00    

fonctions privées virtuelles? ça sert à quoi dans un beau design OO?

Reply

Marsh Posté le 11-03-2006 à 12:58:45    

A redéfinir les comportements des classes sans pour autant les rendre publics ni changer l'interface


Message édité par slash33 le 11-03-2006 à 13:00:36
Reply

Marsh Posté le 11-03-2006 à 13:26:16    

Oui, en gros, séparer l'interface de la customisation.

Reply

Marsh Posté le 11-03-2006 à 19:13:58    

"32. Utilisez les enum pour des constantes de classe entière" ?

Reply

Marsh Posté le 11-03-2006 à 19:17:53    

'tain je dois pas avoir la deuxième édition moi

Reply

Marsh Posté le 11-03-2006 à 19:39:12    

désolé de ne pas avoir précisé l'édition : c'était la 3ème édition.
Après, si tu veux plus de détails, va voir dans les gotw, ou (re)lit un des Herb sutter, mais la, j'ai un peu la flemme de retrouver dans lequel ça apparait ... Je crois que c'est dans le premier. Donc gotw item de 1 à 40 à peu près.

Reply

Marsh Posté le 11-03-2006 à 20:46:27    

++fab a écrit :

Citation :

un carré est hérite également de losange


 
Non, et non. En tout cas pas via un héritage public.


C'est à cause de celà que j'ai cessé de m'intéresser au C++, je suis prof de math, et si le paradigme n'est pas capable de suivre l'évidence mathématique, c'est que (pour moi) le concept est bancal quelque part.
 
D'aucuns diront qu'il faudrait que j'approfondisse le concept, certes je l'ai fait et je l'utilise de temps à autres, mais qu'on trouve un autre exemple pour me prouver que le conception objet est géniale.

Reply

Marsh Posté le 11-03-2006 à 21:36:31    

Trap D a écrit :

C'est à cause de celà que j'ai cessé de m'intéresser au C++, je suis prof de math, et si le paradigme n'est pas capable de suivre l'évidence mathématique, c'est que (pour moi) le concept est bancal quelque part.


 
La clé, c'est de comprendre ce que veux dire la relation "est un" en C++. Quand tu écris class Carre : public Rectangle {}; tu ne dis pas vraiment qu'un carré est un rectangle comme on l'entend en français, mais plutot qu'un carré peut etre utiliser comme un rectangle. Et qu'est-ce qui caractérise un rectangle ? Son interface. Et il y a peu de chances pour que cela ait pleinement un sens pour un carré.
 
L'exemple de B&N est plus clair :
Un pingouin est un oiseau.  
 

Code :
  1. struct Oiseau { virtual void vole() { /* il vole */ };
  2. struct Pingouin : Oiseau { void vole() { /*hem hem probleme*/ } };


 
En fait, ici, ce qui caractérise un oiseau, c'est son interface, le fait qu'il puisse voler. Non qu'il appartienne à la famille des oiseaux.
 

Citation :

D'aucuns diront qu'il faudrait que j'approfondisse le concept, certes je l'ai fait et je l'utilise de temps à autres, mais qu'on trouve un autre exemple pour me prouver que le conception objet est géniale.


Elle n'est pas génial de mon point de vue, et elle ne convient pas tout le temps. Note qu'il n'y a pas *une* façcon de voir la POO, chaque langage à la sienne. Le C++ a sa façon de la voir, en privilégiant l'efficacité et le contrôle statique des types, au détriment de l'évidence parfois. D'autres langages font d'autres choix ...
En question subsidiaire, je te laisse réfléchir sur la neutralité de l'UML :)
 
Si tu es prof de math, la programmation générique devrais pouvoir t'intéresser. Le concept est beaucoup plus naturel et très mathématique -- quoique incomplet en attendant la nouvelle norme et les *concepts*, mais c'est une autre histoire ...


Message édité par ++fab le 11-03-2006 à 21:38:45
Reply

Marsh Posté le 12-03-2006 à 01:48:06    

rhaaa, ils gardent pas les mêmes numéros d'une version à l'autre :)

Reply

Marsh Posté le 12-03-2006 à 01:58:21    

cette histoire de carré, si tu pousses ton exemple à fond, tu arrives toi même à la même conclusion qu'un carré 'a les mêmes propriétés que' un rectangle, ce qui est différent de 'est implémenté en terme de'.
 
En gros quand tu codes tu commences comme ça :  
 
struct Quadrilatère { Côté côtés[4]; }
struct Rectangle : Quadrilatère { // quel gachis ! }
struct Carré : Rectangle { // là c'est vraiment n'importe quoi ! }
 
et au final tu te dis que y a un truc qui cloche :)
 
 
mais si t'as un langage pourri et pas de cerveau, tu fais comme Java, tu te retrouves avec une Stack : Vector ...
 
 
PS: l'exemple du pingouin est aussi dans le Effective C++. D'ailleurs c'est sans doute mal traduit, le pingouin vole, contrairement le manchot. Exemple caduque donc :)

Reply

Marsh Posté le 12-03-2006 à 02:16:56    

Taz a écrit :

cette histoire de carré, si tu pousses ton exemple à fond, tu arrives toi même à la même conclusion qu'un carré 'a les mêmes propriétés que' un rectangle, ce qui est différent de 'est implémenté en terme de'.
 
En gros quand tu codes tu commences comme ça :  
 
struct Quadrilatère { Côté côtés[4]; }
struct Rectangle : Quadrilatère { // quel gachis ! }
struct Carré : Rectangle { // là c'est vraiment n'importe quoi ! }
 
et au final tu te dis que y a un truc qui cloche :)


 
Exactement. C'est une des nombreuses crasses qui arrivent lorsqu'on hérite publiquement d'une classe concrète. Il y en a d'autres : tu n'a pas mis le destructeur virtuel dans les classes de base ;) Pourtant, on peut légitimement vouloir économiser le pointeur sur la vtbl. Si tu n'utilises pas l'idium NVI, tu peux alors appeler des fonctions virtuelles des classes de base qui ne te sont pas destiné (on avait déjà vu le problème il y a quelques mois).
Le B&N explique aussi que tu exposes l'implémentation, puisque l'utilisation de l'héritage public autorise un Rectangle* à se convertir en Quadrilatere*, ce qui peut avoir un impact sur le code client en cas de changement, etc...
 

Citation :

mais si t'as un langage pourri et pas de cerveau, tu fais comme Java, tu te retrouves avec une Stack : Vector ...


ouaip :)
 

Citation :

PS: l'exemple du pingouin est aussi dans le Effective C++. D'ailleurs c'est sans doute mal traduit, le pingouin vole, contrairement le manchot. Exemple caduque donc :)


Je me suis emmelé les crayons, l'exemple est bien dans effective C++. Et purée, j'avais complètement oublié cette histoire de pingouin/manchot qui vole ou pas :o Tu sais si le gentoo vole ? :D

Reply

Marsh Posté le 12-03-2006 à 10:58:33    

enfin bon, ne diabolise pas trop l'héritage public, ça a du bon tout ça.

Reply

Marsh Posté le 12-03-2006 à 11:28:35    

Entre procédural et objet, me dîtes pas que vous préférez le procédural?

Reply

Marsh Posté le 12-03-2006 à 22:47:24    

Taz a écrit :

enfin bon, ne diabolise pas trop l'héritage public, ça a du bon tout ça.


En fait, je diabolise l'héritage public *d'une classe concrète*.

Reply

Marsh Posté le 12-03-2006 à 22:48:50    

slash33 a écrit :

Entre procédural et objet, me dîtes pas que vous préférez le procédural?


Il y a le choix avec programmation générique aussi ...

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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