c++ à l'aide de la déclaration, de la portée et de contrôle d'accès
Généralement l'usage de la déclaration est utilisée pour mettre en application certaines des fonctions membres des classes de base qui autrement seraient cachés. De ce point de vue, il n'est qu'un mécanisme pour assurer l'accessibilité des informations plus pratique à utiliser.
Cependant: - le "à l'aide de la" déclaration peut également être utilisé pour modifier les contraintes d'accès (pas seulement pour les fonctions, mais aussi pour les attributs). Par exemple:
class C{
public:
int a;
void g(){ cout << "C:g()\n"; }
C() : a(0){}
};
class D : public C{
private:
using C::a;
using C::g;
public:
D() { a = 1; }
};
int main(void){
D d;
cout << d.a << endl; //error: a is inaccessible
C *cp = &d;
cout << cp->a << endl; //works
d.g(); //error: g is inaccessible
cp->g(); //works
return 0;
}
Je pense que cette limitation de l'accès dans la classe dérivée est en fait d'aucune utilité, parce que vous pouvez toujours accéder à g() et un à partir d'un pointeur vers la classe de base. Donc devrait pas y avoir au moins une sorte d'avertissement du compilateur? Ou n'aurait-il pas été encore mieux d'interdire une telle limitation de l'accès d'une classe dérivée? L'utilisation de la déclaration n'est pas la seule possibilité d'ajouter des contraintes à l'accès. Il pourrait également être fait par le biais du remplacement d'une classe de base une fonction le plaçant dans une section avec plus de contraintes d'accès.
Certaines raisonnable exemples où il est, en effet, nessecary pour limiter l'accès dans une telle façon? Si non je ne vois pas pourquoi il devrait être permis.
Et une autre chose: au moins avec g++ le même code compile bien sans le mot 'aide'. Cela signifie que pour l'exemple ci-dessus: il est possible d'écrire des C::a; C::g; au lieu de l'aide de C::a; à l'aide de C::g; Est le premier seulement un raccourci pour le dernier ou il y a des différences subtiles?
//EDIT:
donc, à partir de la discussion et réponses ci-dessous ma conclusion serait:
- il est permis de limiter les contraintes d'accès dans les classes dérivées avec le service public de l'héritage
- il y a des exemples où il pourrait être utilisé
- c'est l'utilisation pourrait causer problème en combinaison avec des modèles (par exemple une classe dérivée n'a pas pu être un paramètre valide pour certains modèles de classe/fonction, alors que c'est la base de l'est)
- un nettoyeur de langue de conception ne doit pas permettre une telle utilisation
- compilateur pourrait au moins une sorte d'avertissement
OriginalL'auteur haselhorstk | 2010-01-18
Vous devez vous connecter pour publier un commentaire.
En ce qui concerne votre déclaration sans
using
: ceux-ci sont appelés "accès déclarations", et ils sont obsolètes. Voici le texte de la Norme, de11.3/1
:Je dirais que le plus souvent il n'est pas bon de changer public membres de privé ou protégé membres dans la classe dérivée, car cela violerait le principe de substitution: Vous savez une classe de base a certaines fonctions, et si vous lancez une classe dérivée, alors vous attendre ces fonctions pour être appelable trop, parce que la classe dérivée est- de base. Et comme vous l'avez déjà mentionné, cet invariant est déjà renforcée par la langue permettant de convertir (qui travaille implicitement!) pour une classe de base de référence, ou de qualifier le nom de la fonction, puis en appelant le (publique) de la fonction.
Si vous voulez interdire à quelqu'un d'appeler un ensemble de fonctions de la base, puis je pense que cela nous indique que le confinement (ou dans de rares cas, privé de l'héritage) est une meilleure idée.
base
références ou des pointeurs peut également passé dans underived
objet, comme il le sera implicitement upcasted àbase
. C'est différent une fois que vous ajoutez des modèles et polymorphisme statique pour le mix. Il est vrai qu'un modèle conçu pour fonctionner sur unbase
argument ne fonctionnera pas sur underived
objet. Mais le but de limiter l'accès pourrait être que (c'est unbase
qui ne peuvent pas être utilisés là-bas)?Principe de Substitution signifie, qu'à chaque fois que vous vous attendez à un Objet de type de base (par exemple, pointeur, un argument de passage, etc.) vous pouvez également passer un Objet d'un "mieux" de type et de meilleurs types en C++ sont issus des classes avec le public de base. Avec les non-publics de l'héritage de la Substitution n'est plus autorisé, en raison des contraintes d'accès. Donc, je pense que changer représentants du public au privé, ne viole pas le principe de substitution dans le patrimoine public, parce que vous ne sont tout simplement pas vraiment restreindre l'accès à des contraintes (toujours disponible à partir de la base). @dribeas: pourriez-vous expliquer le modèle de chose un peu plus?
"chaque fois que vous vous attendez à un objet de type de base, vous pouvez également passer un objet d'un meilleur type" - mais ce n'est violé ici. Imaginez votre itérateur hérite
std::iterator
, et puis neprivate: using iterator::value_type;
- il échouer avec des algorithmes standard: Votre classe ne sera pas en mesure de remplacer un itérateur plus, car il n'y a pas de publicvalue_type
membre. Comme dribeas dit qu'il ne viole pas lorsque vous simplement vérifier dynamique polymorphisme. Mais lorsque les modèles sont en place, cela devient observable.ok, vous avez raison à ce point - mais est-ce encore de substitution? Lorsque vous traitez avec des modèles un exemple concret de ce modèle est généré au moment de la compilation et il n'y a pas de fonction globale prenant un argument d'une certaine classe de base. Je pense que les algorithmes standards sont également des modèles? Et si vous essayez d'utiliser certains de ces algorithmes avec votre classe cet échec au moment de la compilation.
L'accès est seulement vérifié au moment de la compilation, donc si il y a un problème, il le sera au moment de la compilation. Quant à savoir si c'est la substitution... je pense que c'est juste différent. Les algorithmes basés sur des modèles ne sont pas différents de l'équivalent de l'algorithme dans un langage dynamique (pensez python): le réel exigence est que l'interface fournit. Si vous lisez la norme (et jusqu'à ce que les concepts obtenir une deuxième chance d'y aller) les arguments de modèle à la STL, les algorithmes de noms standard des interfaces définies:
ForwardIterator
,RandomAccessIterator
, de sorte que tous les itérateurs sont en quelque sorte des dérivés de ceux-ci.OriginalL'auteur Johannes Schaub - litb
Alors que l'aide de déclaration vous a montré offre un mécanisme permettant de modifier le niveau d'accès (mais seulement en bas), qui n'est pas la principale utilisation de l'informatique dans un tel contexte. Une aide contexte, il est principalement destiné à permettre l'accès à des fonctions qui autrement seraient occultées à partir de la classe de base en raison de la langue de la mécanique. E. g.
OriginalL'auteur workmad3
La déclaration
apporte de la "une" de la toponymie locale, de la portée, de sorte que vous pouvez les utiliser plus tard "une" pointe vers "C::"; depuis que, "C::a" et "a" sont interchangeables, tant que vous n'avez pas déclarer une variable locale avec le nom "un".
La déclaration ne change pas les droits d'accès, vous pouvez accéder à "un" dans la sous-classe seulement parce que "a" n'est pas privé.
OriginalL'auteur Antti Huima