OVH Cloud OVH Cloud

POO - Hériter Rectangle d'un Square

42 réponses
Avatar
David FLEURY
Bonjour,

(posté ailleurs mais sans réponse, je tente ma chance ici, étant plus
porté sur le C++)

dans http://www.objectmentor.com/resources/articles/lsp.pdf à propos du
LSP, l'exemple est donné à base d'un Square héritant d'un Rectangle (à
ne pas faire donc)

Auriez-vous une idée d'exemple qui poserait problème pour le cas d'un
Rectangle héritant d'un Square (ou si, à votre avis, le deuxième exemple
que j'ai codé suffit)?

Voici l'argument mis en avant dans l'article (en C++), je reprends
l'exemple donné dans l'article original :
(Un Square héritant d'un rectangle)

// --------------------------------------------------------------------
#include <iostream>

using namespace std;

class Rectangle {
public:
Rectangle( int w = 0, int h = 0 ) : width_(w), height_(h) {}

virtual int width() const { return width_; }
virtual int height() const { return height_; }

virtual void width( int w ) { width_ = w; }
virtual void height( int h ) { height_ = h; }

private:
int width_;
int height_;
};

class Square : public Rectangle {
public:
Square( int w = 0 )
{
width( w );
}

virtual void width( int w ) {
Rectangle::width( w ); Rectangle::height( w );
}

virtual void height( int h ) {
Rectangle::width( h ); Rectangle::height( h );
}
};

// -------- Utilisation du client -------
void g( Rectangle& r ) {
r.width( 5 );
r.height( 4 );

assert( r.width() * r.height() == 20 );
}

int main()
{
Rectangle r( 2, 3 );
g( r );

Square s( 4 );
g( s );
}

Est-ce que celui là pour l'autre sens serait recevable ?
(un Rectangle héritant d'un Square)

// ---------------------------------------------------------------------
#include <iostream>

using namespace std;

class Square {
public:
Square( int w = 0 ) { width( w ); }

int width() const { return width_; }
void width( int w ) { width_ = w; }

virtual double area() const { return width() * width(); }

private:
int width_;
};

class Rectangle : public Square {
public:
Rectangle( int w = 0, int h = 0 )
{
width( w );
height( h );
}

int height() const { return height_; }
void height( int h ) { height_ = h; }

virtual double area() const { return width() * height(); }

private:
int height_;
};

// -------- Utilisation du client -------
void g( Square& r ) {
r.width( 5 );

assert( r.area() == 25 );
}

int main()
{
Square s( 4 );
g( s );

Rectangle r( 2, 3 );
g( r );
}


Cordialement.

2 réponses

1 2 3 4 5
Avatar
JKB
Le Fri, 27 Apr 2012 10:32:34 +0200,
Lucas Levrel écrivait :
Le 26 avril 2012, JKB a écrit :

Sauf que même en forçant explicitement le type, le compilo n'en a
rien à faire. Avoir une méthode foo(const char *p) et une seconde
foo(int i) fait que foo(0) appelle la version cont char * même si je
prends la peine de coller foo((int) 0).
La solution pas élégante a été de rajouter une méthode pour
gérer explicitement ce cas avec un argument supplémentaire. J'avoue,
ce n'est pas propre.



Pour reprendre l'ECM de Jean-Marc Bourguet :

#include <iostream>

struct C {
void f(int) {
std::cout << "f(int)n";
}

void f(char const*) {
std::cout << "f(char const*)n";
}
};

int main()
{
C c;
c.f(0);
}



est-ce que tu ne peux pas faire :

typedef void(C::*bidouille)(int);
bidouille int_f=&C::f;

puis
(*int_f)(0);

?

C'est peut-être moins clair mais ça éviterait de définir une méthode
supplémentaire.



Il faudrait que je teste...

JKB

--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr
Avatar
Marc
Jean-Marc Bourguet wrote:

JKB writes:

Le Thu, 26 Apr 2012 09:54:54 +0200,
Jean-Marc Bourguet écrivait :
JKB writes:

Pour coder en C ou C++, il faut avoir une bonne hygiène de vie et
savoir ce que l'on fait (et avoir un compilo C++ à peu près exempt
de bug, j'ai trouvé un truc rigolo avec le dernier g++ entre
l'entier 0 et le const char * NULL :-( ).



Vu qu'en C++ NULL doit etre defini a une constante entiere de valeur 0,
je me demande si tu n'as pas trouve quelque chose de conforme, ou meme
de specifie (j'ai pas dit de desirable, C++11 definit un nullptr, pour
eviter certains problemes, mais NULL ne peut pas -- encore? -- etre
definit comme nullptr). Il y a des consequences "interessantes" avec la
surcharge et les templates.



Sauf que même en forçant explicitement le type, le compilo n'en a
rien à faire. Avoir une méthode foo(const char *p) et une seconde
foo(int i) fait que foo(0) appelle la version cont char *



Etrange.

même si je
prends la peine de coller foo((int) 0).



Encore plus. Quelle version?



http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#903
http://gcc.gnu.org/bugzilla/show_bug.cgi?idR145

pour quelques précisions.
1 2 3 4 5