J'ai été en quelque sorte surpris que le code suivant compile et s'exécute (vc2012 & gcc4.7.2)
class Foo {
struct Bar { int i; };
public:
Bar Baz() { return Bar(); }
};
int main() {
Foo f;
// Foo::Bar b = f.Baz(); // error
auto b = f.Baz(); // ok
std::cout << b.i;
}
Est-il correct que ce code se compile correctement? Et pourquoi est-ce correct? Pourquoi puis-je utiliser auto
sur un type privé, alors que je ne peux pas utiliser son nom (comme prévu)?
c++
c++11
auto
private-members
hansmaad
la source
la source
f.Baz().i
c'est également OK, tel quelstd::cout << typeid(f.Baz()).name()
. Le code en dehors de la classe peut "voir" le type renvoyé parBaz()
si vous pouvez le récupérer, vous ne pouvez simplement pas le nommer.private
c'est là une commodité pour décrire les API d'une manière que le compilateur peut aider à appliquer. Il n'est pas destiné à empêcher l'accès au typeBar
par les utilisateurs deFoo
, donc il n'empêcheFoo
en aucune manière d'offrir cet accès en renvoyant une instance deBar
.#include <iostream>
. ;-)Réponses:
Les règles pour
auto
sont, pour la plupart, les mêmes que pour la déduction de type de modèle. L'exemple publié fonctionne pour la même raison que vous pouvez passer des objets de types privés aux fonctions de modèle:Et pourquoi pouvons-nous passer des objets de types privés à des fonctions de modèle, demandez-vous? Car seul le nom du type est inaccessible. Le type lui-même est toujours utilisable, c'est pourquoi vous pouvez le renvoyer au code client.
la source
public: typedef Bar return_type_from_Baz;
à la classeFoo
dans la question. Désormais, le type peut être identifié par un nom public, bien qu'il soit défini dans une section privée de la classe.private: typedef Bar return_type_from_Baz;
àFoo
, comme démontré .typedef
Les identifiants ne sont pas conscients d'accéder aux spécificateurs, publics et privés.Bar
ouSomeDeducedType
? Ce n'est pas comme si je pouvais l'utiliser pour accéder à des membres privésclass Foo
ou quoi que ce soit.Le contrôle d'accès est appliqué aux noms . Comparez à cet exemple de la norme:
la source
Cette question a déjà été très bien répondue par Chill et R. Martinho Fernandes.
Je ne pouvais tout simplement pas laisser passer l'occasion de répondre à une question avec une analogie avec Harry Potter:
https://ideone.com/I5q7gw
Merci à Quentin de m'avoir rappelé la faille d'Harry.
la source
friend class Harry;
manque là-dedans?friend class Dumbledore;
Wizard::LordVoldemort;
au C ++ moderne. Au lieu de cela, il appelleusing Wizard::LordVoldemort;
. (Cela ne semble pas si naturel d'utiliser Voldemort, honnêtement. ;-)Pour ajouter aux autres (bonnes) réponses, voici un exemple de C ++ 98 qui montre que la question n'a vraiment rien à voir avec
auto
toutL'utilisation du type privé n'est pas interdite, il s'agissait uniquement de nommer le type. La création d'un temporaire sans nom de ce type est acceptable, par exemple, dans toutes les versions de C ++.
la source