OVH Cloud OVH Cloud

const et pointeurs ...

9 réponses
Avatar
Hamiral
Bonjour,

J'ai un problème de compréhension de l'usage du mot-clé const.
J'ai une classe qui possède un pointeur, ou des pointeurs, vers des objets.
Pour éviter les risques de fuite mémoire, je voudrais que ce soit toujours
cette classe qui alloue et désalloue ses pointeurs, et non l'utilisateur de
la classe. En revanche, l'utilisateur peut avoir besoin d'agir sur l'objet
pointé. Donc il faut que j'ai une méthode "get" retournant ce pointeur.
Mais, je veux que l'utilisateur ne puisse pas libérer le pointeur, le
modifier etc, mais doit quand même pouvoir appeler des méthodes non const
de l'objet pointé ! Je ne sais donc pas quelle syntaxe je dois utiliser.

Exemple :

class Bar;

class Foo {
public:
Bar* getBar() { return m_bar };

private:
Bar* m_bar;
}


Au niveau de la méthode getBar(), j'imagine que je dois placer un mot-clé
const, mais je ne sais pas comment !

const Bar* getBar() ?
Bar const* getBar() ?
Bar* const getBar() ?

En bref, j'ai vraiment du mal à saisir les différences entre les différentes
syntaxes.

Corrigez-moi si je me trompe :

// Le pointeur est constant, on peut appeler des méthodes non const de
l'objet pointé ?
const Bar* getBar()

// idem ?
Bar const* getBar()

// Le pointeur n'est pas constant, mais l'objet si ? Donc je ne peut pas
appeler de méthodes non const, mais je peux faire pointer ce pointeur sur
autre chose ?
Bar* const getBar()

Merci d'avance pour votre aide précieuse, même si je me doute bien que cette
question a déjà été posée 100 fois. Pourtant, j'ai cherché sur le net, mais
j'ai vraiment du mal à comprendre... Je manque certainement de pratique.
--
Hamiral

9 réponses

Avatar
Franck Branjonneau
Hamiral écrivait:

J'ai un problème de compréhension de l'usage du mot-clé const.

Merci d'avance pour votre aide précieuse, même si je me doute bien
que cette question a déjà été posée 100 fois. Pourtant, j'ai cherché
sur le net, mais j'ai vraiment du mal à comprendre... Je manque
certainement de pratique.


<http://jlecomte.ifrance.com/c++/c++-faq-lite/const-correctness-fr.html>

[18] Utilisation correcte de const

En particulier,

[18.5] Quelle est la différence entre "const Fred* p", "Fred * const
p", et "const Fred * const p"?

devrait répondre à tes interrogations.

Pourquoi retourner un pointeur (autrement dit pourquoi pas une
référence) ?

Pourquoi retourner un pointeur const (un Bar * const) ? (« Pour
m'éviter de le "deleter". » me diras-tu. As tu essayer ?)
(<http://www.gotw.ca/gotw/006.htm> te diras pourquoi retourner
un objet constant)

As-tu réfléchis à la copie et à l'affectation de Foo ?

--
Franck Branjonneau

Avatar
Hamiral
Donc, si je définis ma méthode ainsi :

Bar& Foo:getBar() {
return *m_bar;
}

Cela résoud mon problème ?


--
Hamiral
Avatar
Franck Branjonneau
Hamiral écrivait:

Donc, si je définis ma méthode ainsi :

Bar& Foo:getBar() {
return *m_bar;
}

Cela résoud mon problème ?


C'est probablement ce que je ferais (avec la version
const). L'utilisateur a la permission d'utiliser l'instance de Bar et
il ignore qu'elle est gérée avec un pointeur. Cela ne l'empêchera pas
pour autant de faire un delete & foo.getBar().

--
Franck Branjonneau

Avatar
Hamiral
Franck Branjonneau wrote:

Cela ne l'empêchera pas
pour autant de faire un delete & foo.getBar().


Argh !
Mais il n'existe pas un moyen pour empêcher l'utilisateur de détruire cet
objet ???


--
Hamiral, qui pense qu'il va devoir se contenter d'un bon commentaire
(nécessaire mais pas suffisant)

Avatar
Franck Branjonneau
Hamiral écrivait:

Franck Branjonneau wrote:

Cela ne l'empêchera pas
pour autant de faire un delete & foo.getBar().


Argh !
Mais il n'existe pas un moyen pour empêcher l'utilisateur de détruire cet
objet ???


Oui, il n'y a pas moyen d'empêcher l'utilisateur de détruire cet
objet.

--
Hamiral, qui pense qu'il va devoir se contenter d'un bon commentaire
(nécessaire mais pas suffisant)


Vraiment ? Tes utilisateurs sont si mal éduqués ?

-- Franck, don't cancel my post (sic)


Avatar
Pierre Barbier de Reuille
Franck Branjonneau wrote:

Cela ne l'empêchera pas
pour autant de faire un delete & foo.getBar().


Argh !
Mais il n'existe pas un moyen pour empêcher l'utilisateur de détruire cet
objet ???



Non, mais utiliser l'opérateur delete sur une référence renvoyée est
suicidaire de la part de l'utilisateur ... En C++, on considère que le
programmeur ne fait pas complètement n'importe quoi (même si ça arrive ;) ).

Pierre


Avatar
Hamiral
Franck Branjonneau wrote:

Oui, il n'y a pas moyen d'empêcher l'utilisateur de détruire cet
objet.


Bon, tant pis. Je vais faire avec (ou plutôt sans).

--
Hamiral, qui pense qu'il va devoir se contenter d'un bon commentaire
(nécessaire mais pas suffisant)


Vraiment ? Tes utilisateurs sont si mal éduqués ?


Eh bien, en l'occurrence je serai mon propre utilisateur :)
Mais je cherchais surtout à mettre en place le meilleur mécanisme possible.

--
Hamiral


Avatar
Sylvain
Hamiral wrote on 15/09/2006 22:14:
Franck Branjonneau wrote:

Cela ne l'empêchera pas
pour autant de faire un delete & foo.getBar().


Mais il n'existe pas un moyen pour empêcher l'utilisateur de détruire cet
objet ???


si, en ayant un destructeur interdit d'accès:

class Bar {
private:
~Bar() {}
public:
Bar() {}
friend class Foo;
};

le destructeur de Bar ("~Bar()") sera private si la classe Bar est
réputée finale et protected (et virtual) dans le cas contraire.
l'important est que Foo soit amie.

class Foo {
private:
Bar* bar;
public:
Foo() { // sera chargé d'instancier
bar = new Bar;
}
~Foo() {// sera chargé de libérer
delete bar;
}
Bar& getBar(){
return *bar;
}
};

Foo foo;
delete &foo.getBar(); // error: cannot access private member ...

Sylvain.


Avatar
Alain Gaillard

la classe. En revanche, l'utilisateur peut avoir besoin d'agir sur l'objet
pointé. Donc il faut que j'ai une méthode "get" retournant ce pointeur.


Pourquoi ne pas plutôt permettre à l'utilisateur d'agir sur l'objet via
des méthodes de la classe qui contient l'objet ?

--
Alain