Soit par down-casting avec dynamic_cast<>. Mais ce n'est pas très propre. Tu dois définir un moyen pour désigner que ton objet est en fait un Animal, un Environnement ou un Contenu.
Sinon tu repenses à tes fonctions de ta classe mère, peut-être peux-tu réorganiser ta logique de façon que toutes les méthodes dont tu as besoin sont disponible à partir d'un pointeur de la classe mère.
Mais petite question... Quel est le lien entre Contenu, Animal et Environnement?
Depuis quand le transtypage n'est-il pas très propre .... de deux choses l'une, soit ta classe mère est abstraite et contient des méthodes virtuelles dans ce cas tu utilise un tableau de pointeur sur Contenu et tu appelle tes méthodes sans t'en soucier puisque tu fera appel au polymorphisme, soit ta méthode n'est que dans la classe fille et à ce moment la tu cast ton pointeur sur Contenu en Pointeur sur ta classe fille et tu fais appel à ta fonction comme tu le ferais normalement.
J'ai lu quelquepart qu'il s'agit du polymorphisme dynamique : tu peux faire un tableau de pointeurs vers des Contenu* et tu peux ensuite envoyer des classes filles. Sinon la classe fille est convertie en classe mère pour revenir dans le trableau
J'ai lu quelquepart qu'il s'agit du polymorphisme dynamique : tu peux faire un tableau de pointeurs vers des Contenu* et tu peux ensuite envoyer des classes filles. Sinon la classe fille est convertie en classe mère pour revenir dans le trableau
Elle n'est pas convertie, seulement interpretée comme tel. La preuve est que lorsqu'on créer un tableau d'objets de classe héritée et qu'on passe le tableau à une fonction en tant que pointeur de la classe mère, je vous promet beaucoup de plaisir lors de la lecture du 2e élément!
En fait on m'a conseillé effectivement de rendre la classe Contenu abstraite, avec des méthodes virtuelles qui seront définies dans les classes filles.
En revanche le programme va demander beaucoup de fois de traiter ces méthodes, est-ce vrai que ça va demander plus de ressources que de coutume?
Tab sera un tableau de pointeurs vers Contenu je pense, un tableau d'objets étant beaucoup trop lourd.
Le programme va être plus gros mais ça ne prendra pas plus de temps à utiliser la fonction qu'à copier l'adresse d'un pointeur (ou d'un if, c'est 1 instruction)
Le polymorphisme peut être une solution mais je ne comprend vraiment pas le rapport hierarchique entre tes 3 noms de classe.
Si c'est seulement pour faciliter l'utilisation d'un tableau pour tout tes objets alors c'est une mauvaise utilisation. Ça c'est pour C# ou Java. Il n'y a pas de mot-clé "as" en C++.
En fait on m'a conseillé effectivement de rendre la classe Contenu abstraite, avec des méthodes virtuelles qui seront définies dans les classes filles.
En revanche le programme va demander beaucoup de fois de traiter ces méthodes, est-ce vrai que ça va demander plus de ressources que de coutume?
Tab sera un tableau de pointeurs vers Contenu je pense, un tableau d'objets étant beaucoup trop lourd.
Merci pour vos réponses en tout cas.
Si ta classe Contenu est abstraite tab est OBLIGATOIREMENT un tableau de pointeur sur Contenu car il est impossible d'instancier un objet de la classe abstraite tout comme les méthodes virtuelles pures ne doivent pas etre définie dans la classe mère... Cependant pour ce qui est de la vitesse d'exécution de ton programme, si c'est un exercice tu ne verras pas la différence mais surement que pour un programme plus gros cela pourrait jouer du fait que le typage se fait à l'éxécution du programme.
Très bien, merci à vous, j'ai pris note de vos remarques.
Je vais donc utiliser Contenu en classe virtuelle.
Voici sa déclaration dans mon .h
class Contenu
{
private :
//Attributs
std::string _nomTypeContenu; //prend la valeur CONTENU_ANIMAL ou CONTENU_VIDE
int _x; //Abscisse de la case
int _y; //Ordonnée de la case
public :
//Méthodes
//Contenu(std::string = CONTENU_VIDE, int = 0, int = 0); //Constructeur
void setAbscisse(int x) { _x = x;};
void setOrdonnee(int y) {_y = y;};
bool operator == (Contenu) const; //surdéfinition de l'opérateur de comparaison;
virtual void deplacer(const int[][MAX]) = 0; //Déplacement d'un animal
virtual void retirer(int [][TAILLE_REELLE]) = 0; //Retire un animal
};
Et voici la déclaration de ses classes dérivées :
//classe fille de Contenu
class Animal : public Contenu
{
protected :
//Attributs
int _population ;
public :
//Méthodes
Animal(int = 0) ; //Constructeur
virtual void deplacer(const int[][MAX]); //Déplacement d'un animal
virtual void retirer(int [][TAILLE_REELLE]); //Retire un animal
};
//classe vide fille de Contenu
class Vide : public Contenu
{
//vide
};
//classe mur
class Mur : public Contenu
{
};
Et enfin, les classe elles-mêmes dérivées de la classe Animal :
//classe fille de Animal et petite fille de Contenu
class Poule : public Animal
{
private :
//Attributs
int _nbPv ;
//variables statiques
static char _predateurPoule;
static char _proiePoule;
static int _nbPoule;
public :
//Méthodes
Poule(int = 50); //Constructeur
int getNbPv() { return _nbPv;};
};
//classe fille de Animal et petite fille de Contenu
class Renard : public Animal
{
private :
//Attributs
int _nbPv;
//vriables statiques
static char _proieRenard;
static char _predateurRenard;
static int _nbRenard;
public :
//Méthodes
Renard(int = 50);//Constructeur
};
//classe fille de Animal et petite fille de Contenu
class Vipere : public Animal
{
private :
//Attributs
int _nbPv ;
//variables statiques
static char _proieVipere;
static char _predateurVipere;
static int _nbVipere;
public :
//Méthodes
Vipere(int = 50);//Constructeur
};
Comme ça le problème est posé.
Je n'ai pas encore vu la notion de classe abstraite, mais j'ai compris son fonctionnement.
J'ai mis le constructeur de "Contenu" en commentaire. Ai-je le droit de créer cette classe en laissant le constructeur par défaut, sachant qu'elle est virtuelle?
Car en fait quand je teste ce main :
int main() {
Contenu c1;
Poule p1;
P1 = C1;
cout << "le nombre de points de vie est " << p1.getNbPv() << endl;
return 0;
}
J'obtiens l'erreur suivante :
error : cannot declare variable 'c1' to be of type 'Contenu'
error : because the following functions are abstract
error : virtual void Contenu::retirer(int (*)[8])
error : virtual void Contenu::deplacer(const int (*)[100]) error : no match for 'operator= ' in 'p1 = c1'
Dois redéfinir l'opérateur d'affectation? L'opérateur par recopie ne fonctionne pas entre une classe mère et sa dérivée?
Merci d'avance à ceux qui veulent bien m'éclairer sur cette notion de classes virtuelles. Pourquoi ici elles posent problèmes?
En C++, il faut explicitement utiliser des pointeurs. Contrairement à Java où le type pointeur est le type par défaut (les références Java n'étant que des pointeurs déguisés pour ne pas faire peur)
En C++, il faut explicitement utiliser des pointeurs. Contrairement à Java où le type pointeur est le type par défaut (les références Java n'étant que des pointeurs déguisés pour ne pas faire peur)
PS: "classe virtuelle" ne veut rien dire en C++.
Ok je suppose qu'on parle plutôt de Classes abstraites.
En ce qui concerne les pointeurs, je remplace mon main par ceci :
int main() {
Contenu c1;
Contenu *c;
Poule p1;
Poule *p;
c = &c1;
p = &p1;
*p = *c;
cout << "le nombre de points de vie est " << (*p).getNbPv() << endl;
return 0;
}
L'erreur liée à l'opérateur d'affectation disparait, mais les autres erreurs persistent.
Un tableau de Contenu contient des Contenus (sic). Or Contenue n'est toujours pas instanciable.
Même si elle l'était, le fait quelle soit dérivée (publiquement) fait qu'il est peu probable que cela soit une bonne idée.
Quant à la dernière affectation, c'est définitivement pas une bonne idée quand il y a de l'héritage dans l'air. Mais de toutes façons, Contenu n'est toujours pas instanciable ...
En fait le but ce serait que ce tableau puisse contenir des Poules et des Renard et des Vipères, ou toute autre objet dérivé de Contenu.
C'est pour ça que j'avais déclaré un tableau de Contenu
Merci beaucoup, je vais me pencher sur la solution du tableau de pointeurs (vector m'étant encore totalement inconnu, je suis en 1ère année de DUT informatique).
Je me permets de garder la discussion ouverte car j'aurai surement d'autres questions sur ce problème d'héritages, je pense notamment à l'accès aux méthodes virtuelles.
Merci en tout cas.
EDIT:
j'ai une nouvelle question :
Si maintenant, j'ajoute à la classe Animal, une classe soeur que j'appelle Vide.
Vide est donc la dérivée de Contenu.
Or cette classe Vide n'a pas elle-même de dérivée. Est-ce que cela implique que si je veux instancer un objet de type Vide, je dois y définir toutes les méthodes virtuelles qui sont dans la classe Contenu ?
Car alors je risquerai de me retrouver avec une erreur de type :
error : cannot declare variable 'v1' to be of type 'Vide'
error : because the following functions are abstract
Tu n'as pas redéclarer tes fonctions qui sont virtuelles pures dans la classe mère donc la classe Vide (et Mur) reste abstraite. Tu ne peux pas l'instancier.
Je ne sais pas si définir une classe vide a un interret, comme tu as un tableau de pointeur il te suffit de le remplir de null à l'endroit ou il est vide.
L'intérêt de la classe vide viendra après, dans l'avancement du projet, pour anticiper d'éventuels attributs caractéristiques.
Héritage et accès aux classes
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
* Un wrapper C++ pour sqlite * Une alternative a boost units
* Un wrapper C++ pour sqlite * Une alternative a boost units