Préface
Le titre "Le problème de la réduction de l'accessibilité des sous-classes sur les fonctions de classe parent en Java et C ++" semble être plus académique, mais c'est en effet un problème facile à ignorer. Cet article s'efforce d'élaborer la différence entre cette question dans Java et C ++.
Tout d'abord, nous présenterons ce qui est "la réduction de l'accessibilité des sous-classes par rapport à la couverture de la fonction de classe parent". Pour l'héritage, les sous-classes peuvent remplacer les "fonctions virtuelles" de la classe parent - bien qu'il n'y ait pas de fonctions virtuelles à terme dans Java, toutes les fonctions Java peuvent être considérées comme des fonctions virtuelles, car toutes les fonctions Java peuvent être remplacées par les sous-classes. Ici, nous empruntons uniquement le sens du terme «fonction virtuelle» et ne foulons pas dans les détails de la langue. Java et C ++ permettent de modifier l'accessibilité des fonctions lors de la remplacement. La soi-disant «accessibilité» consiste à utiliser des caractères de contrôle d'accès tels que le public, protégé et privé pour le modifier pour contrôler si la fonction est accessible. Habituellement, l'ordre d'accessibilité est (car il n'y a pas de concept de packages en C ++, le contrôle d'accès aux packages n'est pas pris en compte pour le moment, ce qui n'affecte pas la discussion ici):
public> protégé> privé
Prenez Java comme exemple:
classe Base {Protected void Sayshello () {System.out.println ("Hello in Base"); }} class Child étend la base {public void sayshello () {System.out.println ("Hello in Child"); }} Remarque: la fonction sayHello() ici. Dans la base de la classe parent, cette fonction est modifiée à l'aide du caractère de contrôle d'accès protégé. Et les sous-classes utilisent à la place le public, il n'y aura pas de problème. Lorsque les sous-classes remplacent les fonctions de classe parent, l'expansion de l'accessibilité n'est généralement pas un problème.
Java et C ++ adoptent différentes stratégies lorsque les sous-classes réduisent la remplacement de l'accessibilité aux fonctions de classe parent.
Tout d'abord, prenez Java comme exemple et regardez le code suivant:
classe Base {public void Sayshello () {System.out.println ("Hello in Base"); }} class Child étend la base {private void sayshello () {System.out.println ("Hello in Child"); }}Dans le code ci-dessus, il y aura une erreur de compilation sur la ligne 8 en surbrillance - ce code ne peut pas être compilé du tout! Java ne permet pas aux sous-classes de réduire l'accessibilité lors de l'écrasement des fonctions de classe parent. Quant aux raisons, nous pouvons utiliser un exemple pour illustrer. Par exemple, nous écrivons le code suivant en dehors de la classe:
Base de base = new base (); base.sayhello (); base = new Child (); base.sayhello ();
Si le code précédent peut être compilé, il est possible que lorsque la base pointe vers une nouvelle base (), SayHello () est accessible, mais lorsque la base pointe vers New Child (), Sayhello () ne peut pas être accessible! De l'avis de Java, c'est une contradiction, et ce problème doit être évité. Par conséquent, Java stipule du point de vue du compilateur selon lequel nous ne pouvons pas écrire le code ci-dessus.
Pour C ++, la situation est différente. Jetons un coup d'œil à l'exemple C ++:
Classe Base {public: virtual void sayshello () {std :: cout << "Hello in Base"; }} Class Child: Public Base {private: void sayshello () {std :: cout << "Bonjour en enfant"; }}Ce code est complètement correct en C ++. Notez que la sous-classe ici réduit l'accessibilité lors de l'écrasement des fonctions de classe parent. Si vous ne voyez aucun problème, nous pouvons écrire le code suivant en dehors de la classe:
Enfant enfant; enfant.sayhello (); // ne peut pas être compilé car Sayshello () est le static_cast <base &> (enfant) .sayhello (); // ne peut pas être compilé parce que Sayshello () est public
L'appel de la ligne 2 échoue car chez l'enfant, sayHello() est privé et ne peut pas être appelé externe. Cependant, lorsque nous jetons un objet d'enfant à base à l'aide de static_cast, les choses changent - pour la base, sayHello() est publique, donc elle peut être appelée normalement.
À cette fin, l'exemple suivant peut être trouvé dans la section Access to Virtual Fonctions du Contrôle d'accès des membres standard C ++:
classe B {public: virtual int f ();}; classe D: public b {private: int f ();}; void f () {d d; B * pb = & d; D * pd = & d; pb-> f (); // ok: b :: f () est public, d :: f () est invoqué pd-> f (); // Erreur: d :: f () est privé}À cet égard, la norme C ++ donne une explication:
L'accès est vérifié au point d'appel en utilisant le type d'expression utilisé pour désigner l'objet pour lequel la fonction membre est appelée (b * dans l'exemple ci-dessus). L'accès de la fonction membre dans la classe dans laquelle il a été défini (D dans l'exemple ci-dessus) n'est généralement pas connu.
Il y a deux points clés pour une traduction simple:
Pour cette raison, les appelants C ++ semblent être en mesure d'appeler "intelligemment" des fonctions qui étaient à l'origine inaccessibles à travers des transformations habiles. Un exemple plus pratique est: dans QT, QObject::event() est publique et sa fonction QWidget event() est changée en protégée. Pour plus de détails, vous pouvez lire le code pertinent de QT.
En résumé, lorsque les sous-classes remplacent les fonctions des parents, Java limite strictement que les sous-classes ne peuvent pas réduire l'accessibilité des fonctions, mais C ++ n'a pas cette limitation. Personnellement, je crois que du point de vue de l'ingénierie logicielle, les réglementations Java ont sans aucun doute une signification ingénierie et les appels des fonctions sont plus cohérents. La norme C ++ simplifiera considérablement l'implémentation du compilateur, mais ce n'est pas une bonne référence pour l'ingénierie.
PS: La version officielle de la norme C ++ nécessite un achat, mais le projet peut être téléchargé gratuitement. L'adresse de téléchargement du projet standard C ++ peut être trouvée à la page suivante: https://isocpp.org/std/the-standard
Résumer
Ce qui précède est l'intégralité du contenu de cet article. J'espère que le contenu de cet article a une certaine valeur de référence pour l'étude ou le travail de chacun. Si vous avez des questions, vous pouvez laisser un message pour communiquer. Merci pour votre soutien à wulin.com.