Yo!
Je voudrais savoir si c'est problématique d'ajouter à une classe virtuelle pure
un attribut privé, alors que cette classe n'en possedait pas avant?
Quelles sont les précautions à prendre avec une telle classe?
Merci
Yo!
Je voudrais savoir si c'est problématique d'ajouter à une classe virtuelle pure
un attribut privé, alors que cette classe n'en possedait pas avant?
Quelles sont les précautions à prendre avec une telle classe?
Merci
N’étant pas experte en C++, je penserais que si une classe est virtuelle tu peux bien ajouter des attributs privé cela ne changera grand chose. Apres je ne saisis pas pourquoi rajouter un attribut privé à un classe virtuelle, mais cela doit venir du fait que je suis trop imprégnée des interfaces java.
Par classe virtuelle pure, tu entends bien classe ou toutes les méthodes sont déclarée virtuelle pure ?
Dans ce cas, y mettre un attribut privée me parait peu utile, étant donnée qu'il ne pourra être accédé par personne, ou alors quelque chose m'échappe...
Ca peut avoir du sens.
Tu peux très bien définir qu'un cycle a deux roues, même si tu n'as pas encore défini s'il va avancer par propulsion humaine, thermique, ou électrique, et qu'il n'est donc pas encore constructible.
Dans ce cas, la propriété "a deux roues" est publique, pas privée.
1 / Une classe virtuelle pure n'a pas d'accesseurs qui ne sont pas eux-même virtuels purs (par définition).
2/ Sans accesseur concrets, il est impossible d'accéder aux propriétés privées d'un objet en C++ à partir d'une classe dérivée.
3/ La conclusion s'impose d'elle même : la seule chose que va faire la propriété privée, c'est prendre de la place en mémoire. Personne ne peut y avoir accès - comment, dès lors, lui trouver une utilité quelconque ?
[FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.
Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.
Effectivement; j'avais un peu oublié le côté privé...
Salut,
D'abord, il faut faire attention aux termes utilisés...
On parle de classe abstraite lorsqu'une classe n'est pas instanciable (du fait de la présence de fonctions virtuelles pures) et de fonctions virtuelles pures lorsqu'une fonction est déclarée virtuelle mais que l'on n'est pas en mesure de fournir un comportement correct par manque de données.
les fonctions virtuelles pures sont repérables au fait que leur déclaration est suivie d'un = 0 avant le ";" final.
Rien ne t'empêche de déclarer (et de défininir !! ) une fonction qui n'est pas virtuelle ou qui est virtuelle (non pure ! ) dans une classe abstraite si... tu dispose de suffisemment d'informations pour lui donner un comportement cohérent
A partir de là, il n'est pas du tout impensable de donner un membre privé à une classe abstraite pour autant que... l'une ou l'autre des fonctions non virtuelles pures l'utilise! (si aucune fonction non virutelle pure ne l'utilise, cela ne sert effectivement à rien)
Dans l'exemple de cycle que tu présente, nous pourrions dire que cycle hérite de... véhicule, qui dispose d'une fonction virtuelle pure nombreRoue, définie dans cycle, mais que cycle reste une classe abstraite parce que d'autres fonctions virtuelles pures subsistent dans cette classe:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 class Vehicle { public: virtual Vehicle(); /* une série de fonctions virtuelles pures qui font de Vehicle * une classe abstraite */ virtual energyType energy() const = 0; virtual int weelsCount() const = 0; /* ... */ }; /* un bicycle a deux roues, mais un type d'énergie inconnu */ class Bicycle { public: virtual int weelsCount() const; /* Bicycle reste une classe abstraite parce que energy() est encore * virtuelle pure ;) */ private: int weelsCount_; };
A méditer: La solution la plus simple est toujours la moins compliquée
Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
Compiler Gcc sous windows avec MinGW
Coder efficacement en C++ : dans les bacs le 17 février 2014
mon tout nouveau blog
J'ajouterai qu'il est possible de déclarer une méthode virtuelle comme étant pure (= 0) tout en fournissant une implémentation, utilisable une fois qu'on aura rendu l'instanciation possible dans une classe dérivée.
Pervers, certes..
Comme dit Scott Meyers, ça sert surtout à briller dans les dîners en ville.
C'est peut etre vicieux, mais cela peut, malgré tout, avoir une certaine utilité...
Ce que je vais proposer est tordu, mais, imagine une classe de base dont tu veux interdire l'instanciation, pour laquelle tu as une fonction:
et pour laquelle il n'y a pas vraiment de fonctions candidates "logiques" à être virtuelle pure.
- qui doit vérifier des préconditions / invariants
- qui doit etre réimplémentée dans les classes dérivées
- dont l'implémentation des classes dérivées doit utiliser les préconditions / invariants de la classe de base
- pourquoi pas, qui doit effectuer d'office certaines actions préparatoires / finales
Tu peux implémenter un pattern NVI sous une forme proche de
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 /* dans le fichier d'en-tête */ class MyClass { public: void foo() { /* cette ligne force la vérification des invariants */ MyClass::doFoo(); /* et celle-ci applique NVI pour les classes dérivées */ doFoo(); } private: virtual doFoo() = 0; } /* dans le fichier d'implémentaiton */ void MyClass::doFoo() { /* - vérification des invariants, * - vérification des préconditions * - travaux préparatoires */ } /* la classe dérivée */ class Derived : public MyClass { private: virtual void doFoo() { /* on n'a plus à s'inquiéter des préconditions, invariants ou autres * travaux préparatoires ;) */ } };
A méditer: La solution la plus simple est toujours la moins compliquée
Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
Compiler Gcc sous windows avec MinGW
Coder efficacement en C++ : dans les bacs le 17 février 2014
mon tout nouveau blog
Bof. Il me parait plus propre d'avoir une fonction au nom qui suggère clairement une vérification des préconditions & invariants. Plutôt qu'une fonction au nom qui suggère autre chose, et que l'on pourrait de surcroit appeler par erreur depuis ses supplantations.
Cette astuce (fonction virtuelle pure définie) est surtout utile pour avoir des classes abstraites quand la seule fonction virtuelle d'une classe est son destructeur.
Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...
Ca m'étonne que personne ne l'ai encore dit dans cette discussion mais il y a autre chose (peut être que j'ai zappé si quelqu'un l'a dit) :
Si tu ajoutes des objets membres dans ta classe virtuelle, assures toi bien d'avoir son destructeur déclaré en virtual aussi.
Sinon, tu vas avoir des surprises.
L'idée c'est que tant que tu ne déclares pas le destructeur virtuel, il ne sera pas appelé par les destructeurs des classes enfants dans le cas d'une base virtuelle.
J'imagine que c'est déjà fait, mais dans le doute mieux vaut le rappeler.
Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 struct A { void f(int a) { check_precond_f(a); do_f(a); } protected: ~A() {} private: void check_precond_f(int a) { if (a<42) throw std::range_exception(); } virtual void do_f(int a) = 0; }; struct B : A { private: virtual void do_f(int a); }; ... B b;
PS: "classe virtuelle" ne veut rien dire. Il y a
- classe abstraite
- classe abstraite dont tous les membres sont virtuels purs -- alors que le pattern NVI est pourtant bien mieux
- classe de base virtuelle, relativement à un héritage donné
Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...
Ouaip erreur a force de lire le titre du thread.
Je ne comprends pas le rapport avec ton exemple : d'après le premier post
Donc ce que je dis c'est qu'il faut mettre le destructeur virtuel si il ne l'est as encore sinon ces nouveaux attributs ne seront pas détruits...Je voudrais savoir si c'est problématique d'ajouter à une classe virtuelle pure
un attribut privé, alors que cette classe n'en possedait pas avant?
Quelles sont les précautions à prendre avec une telle classe?
Si son interface définit une politique, ou une interface d'échange avec une API bien précise (dont le rôle n'est pas de fournir un moyen de détruire), je ne vois pas en quoi le destructeur non-public non-virtuel est en contradiction avec le besoin (mal exprimé)
Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...
En fait, c'est plutot l'inverse : si tu ne déclares pas le destructeur de la classe de base, un objet de type dérivé ne sera pas correctement détruit si tu invoque un comportement de destruction (delete) alors que l'objet (de type dérivé) "passe pour être" un objet du type de base
Seule la virtualité du destructeur peut assurer un tel comportement
Luc a tout à fait raison : il est parfois sage de rendre un destructeur protégé (pour que les classes enfants puissent y faire appel, car il faut bien détruire la "part de la calsse de base") et non virtuel.
Cela empêchera, bien sur, de détruire les objets de types dérivés lorsqu'ils "passeront pour etre" du type de base, mais peut, justement apporter une certaine sérénitécar cela force à ne détruire les objets que... quand on sait exactement ce que c'est![]()
A méditer: La solution la plus simple est toujours la moins compliquée
Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
Compiler Gcc sous windows avec MinGW
Coder efficacement en C++ : dans les bacs le 17 février 2014
mon tout nouveau blog
Ah oui j'avais zappé la partie destructeur protected (et j'inverse souvent pour qui ne sera pas détruit si le destructeur n'est pas virtuel visiblement)
Donc ça dépends comment sont gérés les dits objets... si on fait des delete sur la classe abstraite le destructeur virtuel sera donc nécessaire.
Tout à fait :
Si la durée de vie des objets concrets est gérée de "manière commune" (grâce à une collection de pointeurs sur la classe de base), il faudra absolument que le destructeur soit public et virtuel.
Par contre, tu peux parfaitement envisager que la durée de vie de chaque type particulier soit géré séparément...
A ce moment là, tu sauras de toutes manière que chaque objet est d'un type dérivé clairement défini, et tu pourras sans problème le détruire sur base de son destructeur propre.
Celui de la classe de base peut donc parfaitement être protégé, et n'a aucun besoin d'être virtuel![]()
A méditer: La solution la plus simple est toujours la moins compliquée
Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
Compiler Gcc sous windows avec MinGW
Coder efficacement en C++ : dans les bacs le 17 février 2014
mon tout nouveau blog
Partager