Mouais, je pratique depuis suffisamment longtemps pour ne pas avoir besoin de relever ce genre de compliment. Je pense que c'est plutôt toi qui n'a pas compris où je voulais en venir.
Ta vision des choses me laisse surtout penser que tu considères l'héritage comme le mécanisme des
couches d'abstraction, ce qui n'est pourtant pas la même chose même si c'est une des principales utilisations que l'on en fait. Tu peux effectivement utiliser une classe composée de fonctions-membres virtuelles pures ou non pour implémenter une interface, mais cela reste deux notions bien distinctes.
La définition même de l'héritage, c'est d'étendre une classe existante en lui ajoutant des attributs. De fait, une sous-classe B de A est implicitement une A munie d'éléments supplémentaires. Ça suffit à définir l'héritage, et non seulement ça n'implique pas forcément la virtualité, mais ça n'implique pas non plus la surcharge. Voici un exemple trivial :
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class Fiche
{
public:
string Nom;
string Prenom;
string Age;
};
class FicheEtendue : public Fiche
{
public:
string Adresse;
string NumeroDeTelephone;
}; |
On est bien d'accord qu'il y a héritage, et qu'une « FicheEtendue » est sémantiquement une « Fiche ». Or, ici, non seulement il n'y a pas de virtualité mais il n'y a même pas de fonction-membre du tout. Sur ce point, il s'agit donc déjà de deux notions complètement distinctes. À l'usage, toute fonction écrite antérieurement à la rédaction de B peut continuer à fonctionner de manière transparente avec des objets de type B sans même le savoir. Et bien sûr, l'idée première est d'éviter d'avoir à réécrire le même code pour l'objet B que pour l'objet A quand il est officiellement avéré que c'est le même.
Partager