CONNEXION
  • RetourJeux
    • Sorties
    • Hit Parade
    • Les + populaires
    • Les + attendus
    • Soluces
    • Tous les Jeux
    • Gaming
  • RetourActu Gaming
    • News
    • Astuces
    • Tests
    • Previews
    • Toute l'actu gaming
  • RetourBons plans
    • Bons plans
    • Bons plans Smartphone
    • Bons plans Hardware
    • Bons plans Image et Son
    • Bons plans Amazon
    • Bons plans Cdiscount
    • Bons plans Decathlon
    • Bons plans Fnac
    • Tous les Bons plans
  • RetourJVTech
    • Actus High-Tech
    • Intelligence Artificielle
    • Smartphones
    • Mobilité urbaine
    • Hardware
    • Image et son
    • Tutoriels
    • Tests produits High-Tech
    • Guides d'achat High-Tech
    • JVTech
  • RetourCulture
    • Actus Culture
    • Culture
  • RetourVidéos
    • A la une
    • Gaming Live
    • Vidéos Tests
    • Vidéos Previews
    • Gameplay
    • Trailers
    • Chroniques
    • Replay Web TV
    • Toutes les vidéos
  • RetourForums
    • Hardware PC
    • PS5
    • Switch 2
    • Xbox Series
    • Switch
    • Pokemon pocket
    • FC 25 Ultimate Team
    • League of Legends
    • Tous les Forums
  • PC
  • PS5
  • Xbox Series
  • Switch 2
  • PS4
  • One
  • Switch
  • iOS
  • Android
  • MMO
  • RPG
  • FPS
En ce moment Genshin Impact Valhalla Breath of the wild Animal Crossing GTA 5 Red dead 2
Liste des sujets

[C++]Quesque le polymorphisme

godrik
godrik
Niveau 30
23 août 2014 à 21:30:05

il y a une histoire de type casting au moment de l'appel de fonction qui fait que je ne sais concretement pas pourquoi ca compile pour commencer. Mais si tu donnais tout le code, avec la declaration des classes, je pourrais voir ce qu'il se passe. Ce n'est pas un histoire "d'avoir une erreur" c'est une histoire de savoir exactement ce que ton code fait. Et pour savoir ce qu'il fait, il faut connaitre les types exacte, leur declaration et comment ils sont construis.

Donc donnes tout le code!

rangerprice
rangerprice
Niveau 10
23 août 2014 à 22:21:45

Code de main.cpp:

  1. include <iostream>
  2. include <string>
  3. include "Vehicule.h"

using namespace std;

void afficher(Vehicule v) const
{
v.affiche();
}

int main()
{
afficher(Voiture BMW); //Voiture est une sous classe de Vehicule
}

Code de Vehicule.h:

  1. ifndef DEF_PERSONNAGE
  2. define DEF_PERSONNAGE
  1. include <iostream>
  2. include <string>

class Vehicule
{
public:
void affiche() const; //Affiche une description du Vehicule
static void toast();

protected:
int m_prix; //Chaque véhicule a un prix
};

class Voiture : public Vehicule //Une Voiture EST UN Vehicule
{
public:
void affiche() const;

private:
int m_portes; //Le nombre de portes de la voiture
};

  1. endif

Code de Vehicule.cpp:

  1. include "Vehicule.h"

using namespace std;

void Vehicule::affiche() const
{
cout << "Ceci est un vehicule." << endl;
}

void Voiture::affiche() const
{
cout << "Ceci est une voiture." << endl;
}

void Vehicule::toast()
{
cout << "Ceci est une fonction statique" << endl;
}

Je t'ai tout donné là :hap:

godrik
godrik
Niveau 30
23 août 2014 à 23:16:06

Ok, c'est bien ce que je pensais, ce code ne peut pas fonctionner. EN fait il ne doit meme pas compiler.

D'abors la fonction afficher n'est pas une fonction de classe. Et donc elle ne peut pas avoir de qualifier const. si tu vire le const de sa specification ca ne peut toujours pas fonctionner, mais tu as retirer une erreur:

void afficher(Vehicule v)
{
v.affiche();
}

Ensuite cette ligne dans le main n'est pas valide non plus. Probablement tu voulais definir un objet BMW de type Voiture. Et appeller la fonction afficher.

int main()
{
Voiture BMW;
afficher(BMW); //Voiture est une sous classe de Vehicule
}

Mais ca, ca ne fait pas ce que tu penses que ca devrai faire. Ce qui se passe ici est que tu passe une objet de type Voiture a une fonction qui prends un Objet de type Vehicule en parametre. Donc C++ initialize un objet DIFFERENT de type Vehicule qu'il initialise par copie de l'objet BMW upcaster vers le type vehicule. (Le constructeur par copie implicte de Vehicule etant de signature Vehicule::Vehicule (const Vehicule&), le compilateur commence par extraire une reference de BMW de type Voiture, puis l'upcaste vers une reference de type Vehicule et la passe en parametre au constructeur par copie de Vehicule.)

Je pense que ce n'est pas ce que tu voulais, tu voulais certainement passer une reference a l'objet BMW. Il faut donc definir la fonction afficher pour prendre une reference:

void afficher(Vehicule& v)
{
v.affiche();
}

Mais Ca ne regle toujours pas ton probleme. Qui est que tu obtiens le message sur la sortie standard: "Ceci est un Vehicule". En effet c'est logique, tu appelles la fonction affiche sur une reference de type Vehicule, donc le compilateur regarde dans la liste des fonctions de Vehicule et trouve une fonction non-virtuelle a appelle. Et donc il l'appelle.

Ce que tu voulais certainement faire, est declarer la fonction affiche() comme une fonction virtuelle. Une fois que tu ajoutes les deux virtual qui vont bien, la fonction afficher cherche la fonction affiche de Vehicule, trouve une fonction virtual. Elle regarde dans la v-table de l'objet et y trouve l'addresse de la fonction Voiture::affiche. C'est cette fonction qu'elle appelle alors.

Le code final est:

  1. include <iostream>
  2. include <string>

using namespace std;

class Vehicule
{
public:
virtual void affiche() const; //Affiche une description du Vehicule
static void toast();

protected:
int m_prix; //Chaque véhicule a un prix
};

class Voiture : public Vehicule //Une Voiture EST UN Vehicule
{
public:
virtual void affiche() const;

private:
int m_portes; //Le nombre de portes de la voiture
};

void Vehicule::affiche() const
{
cout << "Ceci est un vehicule." << endl;
}

void Voiture::affiche() const
{
cout << "Ceci est une voiture." << endl;
}

void Vehicule::toast()
{
cout << "Ceci est une fonction statique" << endl;
}

void afficher(Vehicule& v)
{
v.affiche();
}

int main()
{
Voiture BMW;
afficher(BMW); //Voiture est une sous classe de Vehicule
}

Comme tu as pu le voir, tous ces problemes la sont des histoires de type et de conversion implicite.

inight
inight
Niveau 9
23 août 2014 à 23:52:53

void afficher(Vehicule v) const
{
v.fonction();
}

J'ai encore jamais vu cette signature de fonction (en java), ça signifie quoi le const rajouté ?

godrik
godrik
Niveau 30
23 août 2014 à 23:54:19

c'est parce que ca n'existe pas en java. const en C++ est un peu l'equivalent de final.

Dark_Chouhartem
Dark_Chouhartem
Niveau 11
23 août 2014 à 23:54:57

iNight :d) Si afficher étaient une méthode de classe, ça signifierait que l'objet n'est pas altéré par l'appel de la méthode :ok:

Du coup c'est utile quand tu veux par exemple avoir une fonction qui effectue des calculs sur ton objet mais que tu veux qu'il reste le même à la fin (i.e. pas d'effets de bords indésirables) :ok:

inight
inight
Niveau 9
24 août 2014 à 00:07:53

Okok merci

godrik
godrik
Niveau 30
24 août 2014 à 00:20:46

Non, ce n'est pas vrai ca. Il peut y avoir des effets de bords dans une fonction const. En particulier tu peux lire un fichier, ecrire sur la sortie standard ou changer n'importe quel objet de porte global.

En C++ ce n'est pas vrai non plus que l'objet est strictement le meme au debut de l'appel de fonction const et a la fin. En particulier, tu peux changer tous les champs qui sont note mutable.

rangerprice
rangerprice
Niveau 10
24 août 2014 à 03:43:59

c'est quoi upcaster :question:

godrik
godrik
Niveau 30
24 août 2014 à 04:12:11

si A est la classe mere et B est une classe derive. Alors une conversion de A* vers B* est un down cast. et une conversion de B* vers A* est un up cast.

Pseudo supprimé
Pseudo supprimé 24 août 2014 à 05:02:58

"Academiquement parlant, on distingue deux type de polymorphismes: Le polymorphisme de type et le polymorphisme de fonction. L'un est le polymorphisme classique des langages oriente objet et l'autre est le polymorphisme des langages fonctionel."

Et pour les langages dynamiques qui utilisent le duck typing ?

foo(bar) {
  bar.fun() // résolution dynamique
}

le type de bar peut être tout et n'importe quoi.

Dark_Chouhartem
Dark_Chouhartem
Niveau 11
24 août 2014 à 14:21:22

godrik :d) Oui, mais je parlais d'effets de bords indésirables, ceux qui changent ta classe quand tu veux juste le résultat d'une addition entre 2 big_int par exemple :(

godrik
godrik
Niveau 30
24 août 2014 à 17:27:59

Mais c'est important de noter l'existence de ces changement potentiel parcequ'ils empechent le compilateur de faire de nombreuse optimisation. En particulier appeller une fonction const deux fois de suite pourrait ne pas donner deux fois le meme resultat.

Sous forums
  • Aide à l'achat Mac
  • Création de Jeux
  • Linux
  • Programmation
  • Création de sites web
  • Internet
  • Steam Deck
  • Macintosh
  • Hardware
La vidéo du moment