Ne Sous-Classes Vraiment Hériter Des Variables De Membre Privé?
Fondamentalement, autant que je sache, lorsque vous créez une classe de base avec un public, protected et private section et les variables/fonctions de chaque public et protégé par des sections avoir hérité dans la section appropriée de la sous-classe (définie par la classe sous-classe : privé de base, qui aura tout public et protégé les membres de la base et de les mettre en public, de changer le mot du privé au public les met tous dans le public et de le changer pour protégé les met tous dans protégé).
Ainsi, lorsque vous créez une sous-classe, vous de ne jamais rien recevoir de la partie privée de la classe précédente (la classe de base dans ce cas), si cela est vrai, alors un objet de la sous-catégorie ne devrait jamais avoir sa propre version d'une variable privée ou la fonction de la classe de base correcte?
Arrêtons-nous sur un exemple:
#include <iostream>
class myClass //Creates a class titled myClass with a public section and a private section.
{
public:
void setMyVariable();
int getMyVariable();
private:
int myVariable; //This private member variable should never be inherited.
};
class yourClass : public myClass {}; //Creates a sub-class of myClass that inherits all the public/protected members into the
//public section of yourClass. This should only inherit setMyVariable()
//and getMyVariable() since myVariable is private. This class does not over-ride any
//functions so it should be using the myClass version upon each call using a yourClass
//object. Correct?
int main()
{
myClass myObject; //Creates a myClass object called myObject.
yourClass yourObject; //Creates a yourClass object called yourObject
yourObject.setMyVariable(); //Calls setMyVariable() through yourObject. This in turn calls the myClass version of it because
//there is no function definition for a yourClass version of this function. This means that this
//can indeed access myVariable, but only the myClass version of it (there isn't a yourClass
//version because myVariable is never inherited).
std::cout << yourObject.getMyVariable() << std::endl; //Uses the yourClass version of getMyVariable() which in turn
//calls the myClass version, thus it returns the myClass myVariable
//value. yourClass never has a version of myVariable Correct?
std::cout << myObject.getMyVariable() << std::endl; //Calls the myClass version of getMyVariable() and prints myVariable.
return 0;
}
void myClass::setMyVariable()
{
myVariable = 15; //Sets myVariable in myClass to 15.
}
int myClass::getMyVariable()
{
return myVariable; //Returns myVariable from myClass.
}
Maintenant, en théorie, fondée sur ce que je pense, cela devrait afficher:
15
15
En raison de cela simplement en utilisant toujours le myClass version de fonctions (donc à l'aide de la myClass mavariable). Mais, étrangement, ce n'est pas le cas. Le résultat de l'exécution de ce programme imprime:
15
0
Cela me fait me demander, sommes-nous en réalité pas seulement hériter mavariable, mais ne nous ont également la possibilité de s'amuser avec elle? Clairement, c'est la création d'une version alternative de mavariable en quelque sorte, sinon il n'y aurait pas un 0 pour le myClass version. Nous sommes en effet à l'édition d'un second exemplaire de mavariable en faisant tout cela.
Quelqu'un peut-il m'expliquer ce tout pour moi, cela a déchiré ma compréhension de l'héritage.
- Pourriez-vous s'il vous plaît corriger l'indentation de ton code?
myObject.getMyVariable()
est un comportement indéterminé.- Vous n'appelez jamais
myObject.setMyVariable
. C'est donc un codage simple bug; rien à voir avec l'héritage! - Je pense que c'est peut-être une certaine confusion à propos de la distinction entre les classes et les objets et l'idée fausse que cette distinction en quelque sorte disparaît dès que vous utilisez l'héritage.
Vous devez vous connecter pour publier un commentaire.
Il y a un peu de confusion dans la présente déclaration.
Rappeler que l'héritage est défini pour les classes et les structures en C++. Des objets individuels (ie. les instances) n'héritent pas d'autres objets. La construction d'un objet à l'aide d'autres objets est appelé composition.
Lorsqu'une classe hérite d'une autre classe, il obtient tout ce à partir de cette classe, mais le niveau d'accès de l'héritage de champs peuvent inhiber leur utilisation au sein de l'héritier.
En outre, il existe 3 types de succession pour les classes:
private
(qui est la valeur par défaut),protected
, etpublic
. Chacun d'eux modifie le niveau d'accès d'une classe de propriétés et de méthodes héritées par une sous-classe.Si nous commander les niveaux d'accès de cette manière:
public
,protected
,private
, du moins protégés pour la plupart protégés, alors on peut définir l'héritage des modificateurs de relever les niveaux d'accès de la classe héritée des champs à au moins le niveau qu'ils désignent, dans la classe dérivée (ie. la classe héritant).Par exemple, si la classe
B
hérite de la classeA
avec leprotected
héritage modificateur:ensuite tous les champs de
A
aura au moins leprotected
niveauB
:public
champs deviennentprotected
(public
niveau est élevé àprotected
),protected
champs séjourprotected
(même niveau d'accès, donc pas de modification ici),private
champs séjourprivate
(le niveau d'accès est déjà au-dessus de l'indicateur)"Lorsque vous créez une sous-classe, vous de ne jamais rien recevoir de la section privée de l' [classe de base]. Si cela est vrai, alors un objet de la sous-catégorie ne devrait jamais avoir sa propre version d'une variable privée ou la fonction de la classe de base, correct?"
Pas. La classe dérivée hérite de tous les membres de la classe de base, y compris privés. Un objet de la classe héritée a les membres, mais n'a pas accès direct à eux. Il a accès aux membres publics de la classe de base qui peuvent avoir accès à ces membres, mais elle (la classe dérivée) peut ne pas avoir de nouvelles fonctions de membre avec un tel accès:
yourObject
est en quelque sorte l'accèsmyObject
, ils sont différents des objets!)myObject
etyourObject
sont deux objets différents! Pourquoi devraient-ils partager quoi que ce soit?Pensez-y de cette façon: Oublier l'héritage et supposons que vous avez une classe
Person
avecprivate int age;
etpublic void setAge (int age) {...}
. Vous ensuite instancier deux objets:Vous vous attendriez à ce projet de Loi 35 maintenant, trop? Vous ne voudriez pas, pas vrai? De même, votre
myObject
ne pas partager ses données avecyourObject
.En réponse à votre commentaire:
La classe
yourClass
hérite demyClass
. Cela signifie que les deuxyourObject
etmyObject
ont leur propremyVariable
, le dernier, évidemment, par définition, l'ancien hérité demyClass
.Physiquement, tous les membres( y compris les fonctions de membre) de la classe de base va dans la sous-classe. N'a pas d'importance si elles sont privées. N'a pas d'importance si vous héritez de les communiquer au public/protected ly/privé. Donc dans votre exemple,
yourClass
contient tous les trois degetMyVariable()
,setMyVariable()
etmyVariable
. Tout cela est assez simple, d'accord?Ce qui importe est de savoir comment nous pouvons y accéder. C'est comme quand un fichier est supprimé de votre système. Donc, vous devez d'abord comprendre la différence entre un membre n'étant pas là et un membre, mais inaccessible. Supposons maintenant que toutes les successions a lieu publiquement. Ensuite, tous les membres publics de la classe de base sont publiques dans la classe dérivée, protégé membres sont protégés et les membres privés sont inaccessibles. Ils sont inaccessibles et pas inexistante, car il peut y avoir certaines fonctions membres protégées et des sections publiques dans la classe de base dont l'accès aux membres privés de la classe de base. Ainsi, nous avons besoin de tous les membres de la base qui sont accessibles par le public et les membres protégés fonctions de base, en fonction de leurs fonctionnalités. Depuis il n'ya aucun moyen que nous pouvons déterminer quel membre est nécessaire par le membre qui a la fonction d'une manière simple, nous incluons tous les membres privés de la classe de base dans la classe dérivée. Tout cela signifie simplement que dans une classe dérivée, un membre privé peut être modifié seulement par le biais de la classe de base des fonctions de membre du.
Remarque: chaque membre privé est accessible, directement ou indirectement (par l'entremise d'une autre fonction membre privée qui, à son tour, est appelée par un public/protected fonction membre] par un public/protected meber fonction, sinon il n'a aucune utilisation.
Donc, nous savons que jusqu'à présent qu'une variable membre privée de la classe de base a son utilisation dans la classe dérivée c'est à dire pour la fonctionnalité de ses publics/fonctions membres protégés. Mais ils ne peuvent pas être directement accessible dans la classe de base.
Maintenant, nous nous tournons notre attention vers des secteurs public/privé de l'héritage. Pour le patrimoine public, ce qui signifie que tous les membres accessibles de la classe de base (qui est, le public et les membres protégés) ne peut pas être à un niveau plus permissif que le public. Depuis, le public est le plus permissif niveau, le public et les membres protégés restent dans le domaine public. Mais en privé et protégé à l'héritage, à la fois protégés et privés dans la classe dérivée, respectivement. Dans ce dernier cas, puisque tous ces membres sont privés, ils ne peuvent pas être accessible plus loin dans la hiérarchie de la chaîne, mais peut être consulté par la dérivée de la classe tout de même.
Ainsi, le niveau de chaque membre de classe de base dans la classe dérivée est le moindre de leur niveau dans la classe dérivée () et le type d'héritage (public/protected/private).
Même concept s'applique à des fonctions à l'extérieur de la classe. Pour eux, membres privés et protégés sont accessibles, mais ils existent et peuvent être accessibles par les fonctions membres publiques.
Et de prendre votre cas, comme un dernier exemple,
setMyvariable()
etgetMyVariable()
pouvez accéder àmyVariable
dans la classe dérivée. Mais pas de fonction spécifiée dans la classe dérivée peut accéder àmyVariable
. La modification de votre classe:Plus loin: vous pouvez ajouter des exceptions pour le type d'héritage trop par exemple, un privé de l'héritage à l'exception d'un membre du public dans la classe dérivée. Mais c'est une autre question tout à fait.
Vous n'appelez jamais
myObject.setMyVariable()
, doncmyObject.getMyVariable()
ne sera pas de retour 15.private
n'implique passtatic
.private
n'implique passtatic
...Après:
il n'y a toujours qu'une seule variable de membre. Mais il y a deux façons d'y accéder par le nom:
myClass::myVariable
, etyourClass::myVariable
.Dans ces expressions, le nom de la classe est connue comme la de nommage classe. La seconde chose à comprendre est que droits d'accès s'appliquent à la combinaison de la dénomination de la classe et le nom du membre, et non seulement le nom du membre et de ne pas la variable elle-même.
Si un membre est mentionné sans devoir explicitement la dénomination de la classe, alors la dénomination de la classe est déduit à partir du type de l'expression à gauche de la
.
ou->
qui a nommé le membre (avecthis->
être implicite si ce n'est pas l'expression).En outre, il y a vraiment quatre types d'accès:
public
,protected
,private
, et pas accès. Vous ne pouvez pas déclarer un membre comme ayant pas accès, mais cette situation se présente lorsqu'un membre privé est héréditaire.L'application de tous de cette théorie, votre exemple:
myClass::myVariable
estprivate
.yourClass::myVariable
est pas accès.Le redis, il est seulement fait d'une seule variable, mais il peut être nommé de deux façons différentes, et les droits d'accès diffèrent selon que le nom est utilisé.
Enfin, de retour à l'original de votre exemple.
myObject
etyourObject
sont des objets différents. Je pense que vous l'intention d'écrire, ou de ce que vous êtes mentalement imagination est en fait cette situation:qui signifie
myObject
noms de la classe de base de la partie deyourObject
. Puis après:la variable est définie à
15
, et ainsi deserait sortie de
15
parce qu'il n'y est en effet d'une seule variable.Cela peut aider