La fonction membre const peut-elle renvoyer un pointeur non-const à un membre de données?
Le Code passe en premier:
class A
{
public:
...
int *foo() const
{
return _px;
}
private:
int *_px;
}
La fonction membre foo
renvoie un pointeur non const sur private
member _px
, ce qui, je pense, ouvre une porte à la modification du Membre _px
, n'est-ce pas?
Est foo
une fonction membre const
? Dois-je ajouter un const
devant le type de retour?
Mise à JOUR
Ce qu'une fonction const-member devrait garantir, c'est qu'elle ne peut pas changer de membre de données, n'est-ce pas?
Dans mon cas, la fonction foo
n'ouvre pas la porte à la modification class A
s data-member _px
, mais une porte à modifier ce que _px
pointant vers, donc ma question Est, cela viole-t-il ce qu'une fonction const devrait garantir?
5 réponses
Une fonction membre const
ne peut renvoyer qu'un pointeur const
ou une référence à un membre.
Cependant, votre exemple ne renvoie pas un pointeur à un membre; il renvoie une copie d'un membre qui se trouve être un pointeur. Cela est autorisé dans une fonction membre const
(même si le pointeur pointe vers un autre membre).
Cela ne serait pas autorisé (notez qu'il renvoie maintenant une référence):
int *& foo() const {return _px;}
Mais ceci (renvoyant une référence const
):
int * const & foo() const {return _px;}
int *_px
devient int *const _px
dans une fonction membre const cela implique que le pointeur ne peut pas être reseated mais les données pointées sont toujours modifiables. En outre, votre fonction renvoie une copie du pointeur, ce qui n'a pas d'importance de toute façon.
Cela n'ouvre pas la porte à la modification de _px
mais plutôt à ce que _px
pointe. C'est à vous de décider si vous souhaitez autoriser ou non.
Par exemple, un iterator::operator->
renverrait un pointeur non-const et const_iterator::operator->
renverrait un pointeur const. Les deux méthodes peuvent être const eux-mêmes.
Oui, pour votre cas, il peut. Cependant, il est généralement conseillé de ne pas le faire, car cela permet de changer les objets constants:
void f(const A& a)
{
*(a.foo()) = 42; // damn!
}
Oui, par exemple, voir les pointeurs std::streambuf:
protected:
char* pbase() const;
char* pptr() const;
char* epptr() const;