2009-07-29 7 views
14

J'essaye de créer une classe avec deux méthodes avec le même nom, utilisées pour accéder à un membre privé. Une méthode est publique et const qualifiée, l'autre est privée et non-const (utilisée par une classe d'amis pour modifier le membre au moyen d'un retour par référence).fonction de membre const non-const et public - coexistant en paix?

Malheureusement, je reçois des erreurs de compilation (en utilisant g ++ 4.3): Quand j'utilise un objet non-const pour appeler la méthode, g ++ se plaint que la version non const de ma méthode est privée, même si la version existe.

Cela semble étrange, car si la version privée non-const n'existe pas, tout compile bien.

Y at-il un moyen de faire ce travail? Compile-t-il sur d'autres compilateurs?

Merci.

Exemple:

class A 
{ 
public: 
    A(int a = 0) : a_(a) {} 
public: 
    int a() const { return a_; } 
private: 
    int & a()  { return a_; } /* Comment this out, everything works fine */ 
    friend class B; 
private: 
    int a_; 
}; 


int main() 
{ 
    A  a1; 
    A const a2; 

    cout << a1.a() << endl; /* not fine: tries to use the non-const (private) version of a() and fails */ 
    cout << a2.a() << endl; /* fine: uses the const version of a() */ 
} 
+0

Pourquoi serait-ce un échec? C++ permet la conversion de non-const en const, vis-à-vis d'un paramètre de fonction. – jkeys

Répondre

13

résolution de surcharge se produit avant le contrôle d'accès, de sorte que lorsque vous appelez la méthode sur un non-const A, le membre non-const est choisi comme une meilleure correspondance. Le compilateur échoue ensuite en raison de la vérification d'accès.

Il n'y a aucun moyen de "faire ce travail", ma recommandation serait de renommer la fonction privée. Est-il nécessaire d'avoir un accesseur privé?

+0

Une classe cachée serait mon meilleur pari - comme l'utilisation d'une structure de nœud dans une classe plus grande. – jkeys

+0

C'est trop mauvais. Je pensais que ce serait le cas, mais je ne vois pas pourquoi ça doit être le cas. J'espère que quelqu'un me montrera pourquoi il doit l'être, afin que je puisse me reposer facilement. La raison pour laquelle je veux ce comportement est que j'écris habituellement mes getters et setters comme deux const/non-const version de la même méthode, sans le préfixe "get"/"set". Pour cette classe particulière, je ne veux permettre à aucune classe sauf une d'utiliser les setters (d'où la déclaration de classe friend). – mmocny

+0

La fonction de surcharge est principalement utile lorsque les fonctions exécutent la même opération logique, ou une opération similaire, mais sur un type d'argument différent (particulièrement utile pour l'écriture de code générique dans les modèles). Récupérer la valeur de quelque chose est une opération différente d'obtenir une référence à quelque chose afin de le mettre à jour. Pour cette raison, il est logique (pour moi au moins!) De donner des noms différents aux fonctions. Je pense que vous «nagez contre le courant» si vous essayez de garder les mêmes noms. –

2

Il ne sélectionnera la version const que si l'objet est déclaré est const, sinon il sélectionnera la version non const (même si cela entraîne une erreur).

Cela devrait fonctionner:

cout << ((const A*)&a1)->a() << endl; 

ou ceci:

A const& ra1 = a1; 
cout << ra1.a() << endl; 
+1

Je pense que je préfèrerais 'const_cast (a1) .a()'. Cela semblerait un peu plus sûr –

+0

Oui, c'est le meilleur Je ne pense pas que ce soit plus sûr que la seconde méthode, cependant, le compilateur appliquera la sécurité de type complet pour l'assignation à la référence. ceci en changeant, par exemple, les signatures de méthodes de 'A &' à A const & 'quand vous passez ces choses, plutôt que de les manipuler directement comme dans cet exemple manifestement artificiel –

+1

Je ne comprends pas pourquoi la réponse de Charles Bailey a un tel vote plus élevé que cette réponse (à mon humble avis correct et de travail) de Tim Sylvester qui montre le contraire de _Il n'y a aucun moyen de "faire ce travail" _ En fait, je suis venu ici parce que je savais que J'ai trouvé un tel problème quelque part dans mon code mais j'ai oublié où et comment. (Je l'ai résolu exactement comme décrit ci-dessus Peut-être, je devrais essayer de google sur mon propre code source local la prochaine fois ...) – Scheff

Questions connexes