Pourquoi la conversion entre * dérivé à la base * échoue avec l'héritage privé?
-
01-10-2019 - |
Question
Voici mon code -
#include<iostream>
using namespace std;
class base
{
public:
void sid()
{
}
};
class derived : private base
{
public:
void sid()
{
}
};
int main()
{
base * ptr;
ptr = new derived; // error: 'base' is an inaccessible base of 'derived'
ptr->sid();
return 0;
}
Cela donne une erreur de compilation.
error: 'base' is an inaccessible base of 'derived'
Étant donné que le compilateur va essayer appeler la classe de base sid()
pourquoi dois-je obtenir cette erreur? Quelqu'un peut-il s'il vous plaît expliquer.
La solution
11.2 $ / 4 états -
Une classe de base B de N est accessible à R, si
- un membre du public a inventé de B serait un membre de public N, ou
- R se produit dans un organe ou un ami de la classe N, et un public inventé membre B serait un privé ou membre protégé de N, ou
- R se produit dans un organe ou un ami d'une classe P dérivé de N, et un inventé membre public de B serait membre privé ou protégé de P, ou
- il existe une classe S tel que B est une classe de base de S accessible à R et S est une classe de base de N accessibles à R ".
Ici, 'B' est 'base', 'N' est 'dérivés' et 'R' est principal.
-
Considérez la 2ème-balles R se produit dans un membre ou un ami d'une classe N, .... Cette clause ne concerne pas 'R' (principal) est ni membre ni ami de 'N' (dérivé)
-
Considérez le 3-balles « R se produit dans un membre ou un ami d'une classe P .... ». Cette claus ne s'applique pas pour les mêmes raisons que ci-dessus
-
Considérez le 4 Encore une fois cette-balles clause ne s'applique pas
Nous pouvons donc conclure que « la base » n'est pas une classe accessible de « dérivé ».
11.2 $ / 5 États -
Si une classe de base est accessible, on peut convertir implicitement un pointeur vers une classe dérivée à une pointeur sur cette classe de base (4.10, 4.11). [Note: Il en résulte que les membres et amis d'une boîte classe X convertir implicitement un X * à un pointeur à une société privée ou protégée immédiate classe de base de X. Note -end]
Depuis Base
n'est pas une classe accessible Derived
quand on y accède en main
, la conversion standard de classe dérivée à la classe de base est mal formé. D'où l'erreur.
EDIT 2:
Étudier les messages d'erreur de certains compilateurs populaires et qui devrait vous aider à obtenir une meilleure compréhension. Notez comment le mot « inaccessible » apparaît si souvent et de manière cohérente à travers tous les messages d'erreur
Les références proviennent du projet N3000 standard. Je suis encore télécharger la dernière version:)
GCC prog.cpp: En fonction « int main () »: prog.cpp: 27: erreur: « base » est une base inaccessible de « dérivée »
Comeau en ligne "ComeauTest.c", ligne 26: Erreur: conversion de la base inaccessible « Base » de classe n'est pas permis ptr = new dérivée;
VS2010 erreur C2243: 'type cast': conversion de « dérivée * » à « base de * » Existe, mais il est inaccessible
Autres conseils
Je soupçonne que le problème est que vous ne pouvez pas convertir un pointeur dérivé à un pointeur de base, comme l'héritage est privées.
Chusbad a fourni un je explication approfondie concernant la norme, essayez de fournir une explication accessible.
En C ++, il y a 3 niveaux d'accès: spécificateurs public
, protected
et private
. Ceux-ci sont censées déterminer qui peut accéder aux méthodes, attributs ou classes de base. Il est typique parmi les langages orientés objet.
Ici, vous avez choisi l'héritage private
. Conceptuellement, cela signifie que vous cherchez à cacher le fait héritant de Derived
de Base
à l'extérieur, ce qui signifie généralement ceci est un détail de mise en œuvre.
Par conséquent, la « extérieur » ne connaît pas cette relation. Ceci est renforcé par le compilateur avec ce message inaccessible
.
D'un point de vue de la conception, l'héritage de private
est généralement pas nécessaire. Soit le principe de substitution Liskov applique et que vous utilisez l'héritage public
, soit il est un détail de mise en œuvre et que vous utilisez la composition.
Vous savez que class derived
hérite de class base
, mais la fonction main()
ne le sait pas. La raison pour laquelle la fonction main()
ne sait pas ce que vous avez fait class derived
Hériter PRIVÉS de class base
.
Par conséquent, lorsque vous essayez d'attribuer new derived
à ptr
, les types de pointeurs ne sont pas compatibles.
Essayez ceci:
#include<iostream>
#include<conio.h>
using namespace std;
class base
{
private:
public:
virtual void sid() // You might want to declare sid virtual
{
cout<<"base";
}
virtual ~base() // You then probably need a virtual destructor as well.
{
}
};
class derived : public base //public inheritance
{
private:
public:
void sid()
{
cout<<"derived";
}
};
int main()
{
base * ptr;
ptr = new derived;
ptr->sid();
getch();
return 0;
}
ce qui donne C2243 d'erreur: 'type cast': la conversion de 'dérivé *' à 'base *' existe, mais est inaccessible Cette classe dérivée a été héritée en privé .donc objet de classe de base n'est pas est créé lorsque la création derieved get arrive. pour créer l'objet derive premiers appels va créer l'objet de classe de base qui ne se produit pas. soltuion est d'obtenir la classe publique. il importe que votre doesn utilisant le mot clé virtuel avec des fonctions membres ou non.
Vous devez déclarer votre fonction sid () dans la classe de base comme virtuel. Une fonction virtuelle peut être remplacée par une classe dérivée. Dans le cas contraire, vous probablement une erreur de compilation.