Héritage et fonction virtuelle

Le
PurL
Bonjour,

Pouvez-vous me dire quel comportement y'a t-il entre ces 2 déclarations :

1/

class A
{

virtual void fct() = 0;

};

class B : public A
{

virtual void fct() = 0;

};

class C : public B
{

void fct() { //code}

};

et :

2/
class A
{

virtual void fct() = 0;

};

class B : public A
{


};

class C : public B
{

void fct() { //code}

};

La différence est que fct n'est pas redéfinie au sein de B.

Merci,

PurL
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Loïc Joly
Le #833858
PurL wrote:
Bonjour,

Pouvez-vous me dire quel comportement y'a t-il entre ces 2 déclarations :

1/

class A
{
...
virtual void fct() = 0;
...
};

class B : public A
{
...
virtual void fct() = 0;
...
};

class C : public B
{
...
void fct() { //code}
...
};



Dans ce cas, la fonction B::fct peut être définie (le =0 n'empêche pas
ça). Exemple où ça peut servir : fct est une fonction "en cascade",
genre save, c'est à dire que la fonction de la classe dérivée doit
commencer par appeler la version de la classe de base. Quand on écrit B,
classe abstraite pour d'autres raisons, on a quand même besoin d'écrire
la fonction B::save pour sauver les données correspondant à B. Et on n'a
pas envie que les gens qui dérivent de B oublient de définir une
fonction save à eux. Donc on déclare B::save virtuelle pure, et on la
défini quand même (remarque : Souvent, dans ce genre de cas, la fonction
est protected).

--
Loïc

Jean-Marc Bourguet
Le #833857
"PurL"
Bonjour,

Pouvez-vous me dire quel comportement y'a t-il entre ces 2 déclarations :

1/

class A
{
...
virtual void fct() = 0;
...
};

class B : public A
{
...
virtual void fct() = 0;
...
};
2/

class B : public A
{
...
...
};

La différence est que fct n'est pas redéfinie au sein de B.


Outre la possibilite de definir fct (voir message de Loïc), il me
semble que ca peut changer la recherche des noms; si fct est surcharge
dans B, un appel a travers un B ne trouvera pas void fct() venant de A
sans la declaration.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

PurL
Le #833646
Dans ce cas, la fonction B::fct peut être définie (le =0 n'empêche pas
ça). Exemple où ça peut servir : fct est une fonction "en cascade",
genre save, c'est à dire que la fonction de la classe dérivée doit
commencer par appeler la version de la classe de base. Quand on écrit
B, classe abstraite pour d'autres raisons, on a quand même besoin
d'écrire la fonction B::save pour sauver les données correspondant à
B. Et on n'a pas envie que les gens qui dérivent de B oublient de
définir une fonction save à eux. Donc on déclare B::save virtuelle
pure, et on la défini quand même (remarque : Souvent, dans ce genre
de cas, la fonction est protected).


Je suis d'accord, c'est meme l'effet désirée (cascade) sauf que je n'ai pas
besoin ne redéfinir la fct de B. Je voulais juste savoir ce que cela
changeait pour A.
Si j'ai bien compris, qu'il y ait la déclaration virtual void fct() = 0;
dans B ou pas, ne change rien pour A ?
J'avais un doute dans le fait de ne pas déclarer fct dans B de "casser" la
chaine de l'héritage...

pouvez-vous confirmer ?

Merci,

PurL

Alexandre
Le #833640
Si j'ai bien compris, qu'il y ait la déclaration virtual void fct() = 0;
dans B ou pas, ne change rien pour A ?


oui.

J'avais un doute dans le fait de ne pas déclarer fct dans B de "casser" la
chaine de l'héritage...


non, n'étant pas redéclarée, la version de A est utilisée, donc la fonction
est présente mais en virtuelle pure.


pouvez-vous confirmer ?

Merci,

PurL




drkm
Le #837064
Jean-Marc Bourguet
"PurL"
1/

class A
{
virtual void fct() = 0;
};

class B : public A
{
virtual void fct() = 0;
};


2/
class B : public A
{
};

La différence est que fct n'est pas redéfinie au sein de B.


Outre la possibilite de definir fct (voir message de Loïc), il me
semble que ca peut changer la recherche des noms; si fct est surcharge
dans B, un appel a travers un B ne trouvera pas void fct() venant de A
sans la declaration.


J'ai du mal à comprendre ce que tu veux dire. En tout cas, ceci
fonctionne comme prévu :

~> cat fclcxx.cc
#include <iostream>
#include <ostream>

struct A {
virtual void fct() = 0 ;
} ;
struct B : A {
virtual void fct() = 0 ;
} ;
struct C : B {
void fct() {
std::cout << "C::fct()" << std::endl ;
}
} ;

struct X {
virtual void fct() = 0 ;
} ;
struct Y : X {
} ;
struct Z : Y {
void fct() {
std::cout << "Z::fct()" << std::endl ;
}
} ;

int main() {
B * b = new C() ;
Y * y = new Z() ;
b->fct() ;
y->fct() ;
}
~> g++ -o fclcxx fclcxx.cc -Wall -ansi -pedantic
~> ./fclcxx
C::fct()
Z::fct()

--drkm


Publicité
Poster une réponse
Anonyme