Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Notion d'interface

4 réponses
Avatar
Zouplaz
Bonsoir, petit question surement bateau comment défini-t-on une
"interface" en C++ ?

J'ai pas bien pigé ce qui est dans la faq.



Sur cette page (http://www.infres.enst.fr/~elc/cpp/coursC++.html) il est
dit (je résume) qu'une interface est un cas particulier de classe abstraite
. Dans l'exemple donné, l'interface est définie comme n'ayant aucune
variable membre ni de constructeur (et bien sur la classe est abstraite).

Alors une classe ne définissant que des fonctions virtuellement pures est
forcément une interface ? Mais à quoi ça sert ??

Comme d'hab (vu mon niveau) une réponse la + simple possible est la
bienvenue. Si c'est une question redondante, un lien suffira ! Merci

4 réponses

Avatar
Michaël Monerau
Zouplaz wrote:
Sur cette page (http://www.infres.enst.fr/~elc/cpp/coursC++.html) il
est dit (je résume) qu'une interface est un cas particulier de classe
abstraite . Dans l'exemple donné, l'interface est définie comme
n'ayant aucune variable membre ni de constructeur (et bien sur la
classe est abstraite).

Alors une classe ne définissant que des fonctions virtuellement pures
est forcément une interface ? Mais à quoi ça sert ??


Une interface est un outil très puissant. Le principe de base est le
polymorphisme (si tu ne connais pas ce principe, tu ne comprendras pas la
notion d'interface). Par exemple (et c'est l'exemple le plus courramment
utilisé), tu définis une classe :

class Shape
{
public:
virtual void Draw () = 0;
};

Ici, on voit bien qu'un objet Shape serait absurde. Pourtant, cette classe
sert beaucoup ! Imagine que tu fasses derrière une arborescence :

class Circle : public Shape
{
public:
virtual void Draw () {/*dessine...*/}
};

class Ellipse : public Shape
{
public:
virtual void Draw () {/*dessine...*/}
};

Maintenant, tu voudrais stocker tous tes objets (Circle et Ellipse) dans un
même tableau ou vector. C'est là que le polymorphisme entre en jeu : avec
seulement un pointeur sur la classe de base, tu peux appeler le bonne
fonction Draw (en fonction de leur classe : ça marche par pointeurs de
fonctions dans la vtable). Donc :

vector<Shape*> vShapes;
vShapes.push_back (new Circle ());
vShapes.push_back (new Ellipse());

et ensuite, tu peux écrire :
vShapes.front ().Draw ();

(ou avec des iterator... enfin, tu comprends le truc : dans une fonction où
tu ne connais pas le type exact du pointeur (tu sais juste qu'il dérive de
Shape), tu peux appeler la bonne fonction Draw). Ensuite, la puissance de
l'interface, c'est que même si tu n'as pas l'implémentation de Circle, ou de
Ellipse (imaginons que c'est une autre librairie ou quoi), tu peux tout de
même appeler Draw() sur un Shape*, et le "bon" Draw sera appelé, dans la
classe dérivée.

J'espère avoir été un minimum clair... sinon, n'hésite pas ;-)
--
<=- Michaël "Cortex" Monerau -=>

Avatar
Zouplaz
Michaël Monerau - :

J'espŠre avoir ‚t‚ un minimum clair... sinon, n'h‚site pas ;-)


Clair ET rassurant !! Parce que, tel monsieur Trucmuch (me souviens plus,
un personnage de Molière) qui faisait de la prose sans le savoir je
définissait donc des interfaces sans le savoir !
Parce que le polymorphisme j'adore et j'abuse ! Si si, j'ai utilisé à
plusieurs reprises le genre de procédé que tu décris.

Donc, l'interface dans ce cas précis c'est la classe de base !

T'es sur de toi hein ? Parce que demain je dois discuter avec le prof de
CPO alors bon... Vaut mieux que j'évite les "bavures" ;-))

Merci !

Avatar
Michaël Monerau
Zouplaz wrote:
Michaël Monerau - :

J'espŠre avoir ‚t‚ un minimum clair... sinon, n'h‚site pas ;-)


Clair ET rassurant !! Parce que, tel monsieur Trucmuch (me souviens
plus, un personnage de Molière) qui faisait de la prose sans le
savoir je définissait donc des interfaces sans le savoir !
Parce que le polymorphisme j'adore et j'abuse ! Si si, j'ai utilisé à
plusieurs reprises le genre de procédé que tu décris.


eheh :) Cool

Donc, l'interface dans ce cas précis c'est la classe de base !


oui.

T'es sur de toi hein ? Parce que demain je dois discuter avec le prof
de CPO alors bon... Vaut mieux que j'évite les "bavures" ;-))


Oui, l'interface est la classe abstraite de base. Comme je te disais, ça
peut permettre d'effectuer des opérations sur des objets dont tu ne connais
pas exactement le type. Par exemple, tu as une librairie qui te renvoie un
"Shape*". Tu ne sais pas exactement si c'est un Circle ou un Ellipse...
Pourtant, tu le stockes dans le vector, et tu peux ensuite l'afficher, même
sans connaître son type (simplement en incluant Shape.h !)... C'est ça qui
est intéressant : tu définis des opérations qui auront un sens pour toutes
les classes dérivées, et tu peux ensuite appeler les fonctions virtuelles en
conséquence...

Dans le Stroustup, l'exemple est un bouton d'interface si je me souviens
bien (avec des fonctions comme "Push", "Draw", etc...). Ca fonctionne aussi
très bien avec des fenêtres, ou des choses comme ça.

Bonne chance pour demain ;-)
--
<=- Michaël "Cortex" Monerau -=>


Avatar
Christophe Lephay
"Zouplaz" a écrit dans le message de
news:
Bonsoir, petit question surement bateau comment défini-t-on une
"interface" en C++ ?

J'ai pas bien pigé ce qui est dans la faq.


Le concept d'interface peut varier selon le langage utilisé. Dans tous les
cas, l'idée consiste à obliger des classes à définir un certain nombre de
fonction membre. On obtient celà en héritant d'une classe de base avec des
fonctions virtuelles pures (qui doivent donc, à priori, être implémentées
dans les classes dérivées).

La notion d'interface diffère un peu en C++ et en Java dans la mesure où
l'héritage d'interface en Java ne peut se faire que pour des fonctions
virtuelles pures, alors qu'en C++, il est courant que qu'on hérite d'un
contrat en même temps que d'une interface. L'idée consiste, dans ce dernier
cas, à faire appeler les fonctions virtuelles définies dans les classes
dérivées par une fonction non virtuelle dans la classe de base :

class interface
{
public:
void qquechose()
{
// préconditions
do_qquechose();
// postconditions
}

protected:
virtual void do_qquechose() = 0;
};

La fonction virtuelle pure do_qquechose() est l'interface au sens académique
du terme (fonction implémentée dans les classes dérivées), tandis que la
fonction qquechose() définit le contrat (par exemple en garantissant des pré
et post conditions dans l'exemple. En rendant les fonctions virtuelles
protected, on s'assure que le contrat est incontournable (l'utilisateur ne
peut appeler que les fonctions non virtuelles responsables de la bonne
exécution du contrat).

En fait, on peut voir deux définitions pour le mot interface :

* des fonctions à implémenter (pour le concepteur de classes dérivées)
Ce sont des fonctions virtuelles pures devant être implémentée par le
concepteur des classes dérivées

* des fonctions accessibles
Ce sont les fonctions accessibles à l'utilisateur (les fonctions public -
voire les fonctions amies - pour qui instancie les objets, les fonctions
public et protected pour qui conçoit des classes dérivées).

Chris