OVH Cloud OVH Cloud

Bug ?

16 réponses
Avatar
Vincent Richard
Bonsoir,

Désolé pour le sujet du message, je ne savais pas quoi mettre...
Le programme suivant ne compile pas :

#include <string>
#include <iostream>

struct A
{
virtual ~A() { }
virtual const std::string f() const { return "toto"; }
virtual const std::string f(int x) const = 0;
};

struct B : public A
{
virtual const std::string f(int x) const { return "titi"; } // l.13
};

int main()
{
B b;
std::cout << b.f() << std::endl; // l.20
}

L'erreur affichée est :

a.cpp: In function `int main()':
a.cpp:20: error: no matching function for call to `B::f()'
a.cpp:13: note: candidates are: virtual const std::string B::f(int) const

Y'aurait-il un bug dans mon compilateur (g++ version 3.4) ou bien ce
comportement est-il normal ? (auquel cas je ne vois vraiment pas ce qui
pose problème.)

Comment contourner le problème (c'est-à-dire, comment permettre l'appel
de "f" sans paramètres, sans renommer la fonction) ?

Vincent

--
vmime, une bibliothèque C++ sous licence GPL pour parser et générer
des messages au format MIME : http://www.sourceforge.net/projects/vmime/

10 réponses

1 2
Avatar
Mathieu Peyréga
étrange... j'ai le même comportement avec Visual C++ 6.0 sp6

j'ai essayé aussi :
#include <cstdlib>
#include <iostream>

class A
{
public:
A() {}
A(A const& a) {}
virtual ~A() { }
virtual int f(int x) const = 0;
virtual int f() const { return 2; }
};

class B : public A
{
public:
virtual int f(int x) const { return 3; }
};

int main(int argc, char *argv[])
{
A *pb = new B;
std::cout << pb->f() << std::endl;
std::cout << pb->f(0) << std::endl;

B b;
std::cout << b.A::f() << std::endl;
std::cout << b.f(0) << std::endl;

return 0;
}

qui fonctionne et aussi

#include <cstdlib>
#include <iostream>

class A
{
public:
A() {}
A(A const& a) {}
virtual ~A() { }
virtual int f(int x) const = 0;
virtual int f(double x) const { return 2; }
};

class B : public A
{
public:
virtual int f(int x) const { return 3; }
};

int main(int argc, char *argv[])
{
A *pb = new B;
std::cout << pb->f(0.0) << std::endl;
std::cout << pb->f(0) << std::endl;

B b;
std::cout << b.f(0.0) << std::endl;
std::cout << b.f(0) << std::endl;

system("PAUSE");
return 0;
}

qui fonctionne aussi. Le problème semble donc être lié au type
d'argument "void" mais je ne sais pas si c'est normal ou pas.


Vincent Richard a écrit:
Bonsoir,

Désolé pour le sujet du message, je ne savais pas quoi mettre...
Le programme suivant ne compile pas :

#include <string>
#include <iostream>

struct A
{
virtual ~A() { }
virtual const std::string f() const { return "toto"; }
virtual const std::string f(int x) const = 0;
};

struct B : public A
{
virtual const std::string f(int x) const { return "titi"; } // l.13
};

int main()
{
B b;
std::cout << b.f() << std::endl; // l.20
}

L'erreur affichée est :

a.cpp: In function `int main()':
a.cpp:20: error: no matching function for call to `B::f()'
a.cpp:13: note: candidates are: virtual const std::string B::f(int) const

Y'aurait-il un bug dans mon compilateur (g++ version 3.4) ou bien ce
comportement est-il normal ? (auquel cas je ne vois vraiment pas ce qui
pose problème.)

Comment contourner le problème (c'est-à-dire, comment permettre l'appel
de "f" sans paramètres, sans renommer la fonction) ?

Vincent



Avatar
Luc Hermitte
Vincent Richard wrote
in news:40a3d446$0$21083$:

[...]
Y'aurait-il un bug dans mon compilateur (g++ version 3.4) ou bien ce
comportement est-il normal ? (auquel cas je ne vois vraiment pas ce
qui pose problème.)


En ne /redéfinissant/ qu'une seule des deux fonctions, tu /masques/
l'autre.

Comment contourner le problème (c'est-à-dire, comment permettre
l'appel de "f" sans paramètres, sans renommer la fonction) ?


Peut-être un "using f;", je ne sais plus.
Autrement, l'option d'avoir les fonctions membres publiques non
virtuelles qui appellent les versions non publiques mais virtuelles
devrait régler ça.

struct A {
// Il peut être pratique de rajouter les vérifications d'invariants
// et autres pre- et post-conditions dans les f.
std::string f() { f_(); }
std::stringf(int i) { f_(i); }
private:
virtual std::string f_() { return "toto"; }
virtual std::string f_(int) = 0;
};

class B : public A {
virtual std::string f_(int) { return "titi"; }
};

--
Luc Hermitte <hermitte at free.fr>
FAQ de <news:fr.comp.lang.c++> :
<http://www.cmla.ens-cachan.fr/Utilisateurs/dosreis/C++/FAQ/>
Dejanews : <http://groups.google.com/advanced_group_search>

Avatar
Franck Branjonneau
Luc Hermitte écrivait:

Vincent Richard wrote
in news:40a3d446$0$21083$:

[...]
Y'aurait-il un bug dans mon compilateur (g++ version 3.4) ou bien ce
comportement est-il normal ? (auquel cas je ne vois vraiment pas ce
qui pose problème.)


En ne /redéfinissant/ qu'une seule des deux fonctions, tu /masques/
l'autre.

Comment contourner le problème (c'est-à-dire, comment permettre
l'appel de "f" sans paramètres, sans renommer la fonction) ?


Peut-être un "using f;", je ne sais plus.


Oui.
--
Franck Branjonneau


Avatar
Franck Branjonneau
Mathieu Peyréga écrivait:

étrange... j'ai le même comportement avec Visual C++ 6.0 sp6


C'est normal.

Le problème semble donc être lié au type d'argument "void" mais je
ne sais pas si c'est normal ou pas.


Non, redéfinir une fonction dans une classe dérivée masque toutes les
fonctions de même nom de la classe de base.

[ Merci de respecter les usages de Usenet ]
--
Franck Branjonneau

Avatar
Fabien LE LEZ
On Thu, 13 May 2004 23:30:38 +0200, Luc Hermitte
wrote:

Peut-être un "using f;", je ne sais plus.


Si mes souvenirs sont bons :

using A::f;


--
;-)
FLL, Epagneul Breton

Avatar
Gabriel Dos Reis
--=-=- Content-Type: text/plain; charset=iso-8859-15
Content-Transfer-Encoding: 8bit

Vincent Richard writes:

| Bonsoir,
|
| Désolé pour le sujet du message, je ne savais pas quoi mettre...
| Le programme suivant ne compile pas :
|
| #include <string>
| #include <iostream>
|
| struct A
| {
| virtual ~A() { }
| virtual const std::string f() const { return "toto"; }
| virtual const std::string f(int x) const = 0;

--=-=- Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit


Surcharger une fonction virtuelle est presque toujours source de maux
de tête.


| };
|
| struct B : public A
| {
| virtual const std::string f(int x) const { return "titi"; } // l.13

La déclaration de cette fonction dans B cache toutes les fonctions
du même nom que f dans la classe de base A. Si tu veux redéfinir une
fonction virtuelle et que tu veux bénéficier de l'effet de surcharge,
il te faut d'abord mettre les fonctions de la class de base dans la
portée de B, i.e.


struct B : A {
// bring A::f into scope before overridding. That way, you
// the overloads too.
using A::f;
const std::string f(int x) const { return "titi"; }
};

[...]

| Y'aurait-il un bug dans mon compilateur (g++ version 3.4) ou bien ce
| comportement est-il normal ?

Comportement normal.

--=-=- Content-Type: text/plain; charset=iso-8859-15
Content-Transfer-Encoding: 8bit


| (auquel cas je ne vois vraiment pas ce qui pose problème.)

--=-=- Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit


Tu as caché les fonctions de la classe de base.

-- Gaby

--=-=-=--
Avatar
Gabriel Dos Reis
"Jean-Noël Mégoz" writes:

| "Gabriel Dos Reis" a écrit dans le message de
| news:
| > Vincent Richard writes:
| >
| > | Bonsoir,
| > |
| > | Désolé pour le sujet du message, je ne savais pas quoi mettre...
| > | Le programme suivant ne compile pas :
| > |
| > | #include <string>
| > | #include <iostream>
| > |
| > | struct A
| > | {
| > | virtual ~A() { }
| > | virtual const std::string f() const { return "toto"; }
| > | virtual const std::string f(int x) const = 0;
| >
| Le fait d'utiliser "struct" plutôt que "class" est-il normal ?

Oui. La différence entre « class » et « struct » relève simplement du
sucre syntaxique. Mais dans les années '80, cela était peut-être
psychologiquement nécessaire pour montrer aux gens qu'il y a quelque
chose de plus que juste du C.

-- Gaby
Avatar
Gabriel Dos Reis
drkm writes:

[...]

| Personnellement, j'utilise « struct » lorsque je déclare une petite
| classe utilitaire dont le but est principalement de regrouper quelques
| valeurs, sans réellement fournir d'autres choses. Par exemple :

Il y a quelques années, je suis devenu très paresseux et j'écris
presque instinctivement « struct foo : bar » au lieu de
« class foo : public bar » (vu que la plupart de mes dérivations sont
publiques) et j'ai été « surpris » de voir que mon boss actuel fait
pareil dans ses codes récents que j'ai pu lire.

Aussi, je mets systématiquement les membres publiques avant les
membres protectés et avant les membres privés. Ainsi, j'ai

struct Overload_impl : Expr_impl<Overload> {
// master declaration for the subscripting type.
const Decl& operator[](const Type&) const;

// number of master declarations in this overload-set
std::size_t size() const;

void accept(Visitor&) const;

void register_decl(Decl*);

protected:
Overload_impl();

const Decl& get(Position) const;

private:
typedef std::map<const Type*, Sequence_impl<Decl> > Overloads;
Overloads masterdecls;

Overload_impl(const Overload_impl&); // not implemented
Overload_impl& operator=(const Overload_impl&); // not implemented
};

-- Gaby
Avatar
Jean-Noël Mégoz
"Gabriel Dos Reis" a écrit dans le message de
news:
Vincent Richard writes:

| Bonsoir,
|
| Désolé pour le sujet du message, je ne savais pas quoi mettre...
| Le programme suivant ne compile pas :
|
| #include <string>
| #include <iostream>
|
| struct A
| {
| virtual ~A() { }
| virtual const std::string f() const { return "toto"; }
| virtual const std::string f(int x) const = 0;

Le fait d'utiliser "struct" plutôt que "class" est-il normal ?


Avatar
Franck Branjonneau
"Jean-Noël Mégoz" écrivait:

Le fait d'utiliser "struct" plutôt que "class" est-il normal ?


La seule différence entre struct et class est que la visibilité par
défaut de la premiére est public alors que celle de la seconde est
privée.
--
Franck Branjonneau

1 2