Bonjour à tous,
je cherche à appeler explicitement la version const d'une fonction membre.
C'est un cas un peu tordu que je résume ici:
J'ai 2 classes abstraites A et B, A utilise B, mais B est fournie par une
classe fille de A:
class B
{
public:
virtual string GetName() const = 0;
};
class A
{
public:
string GetName() const
{
return this->GetB().GetName();
}
protected:
virtual B & GetB() = 0;
};
GetB() est la fonction que les classes filles doivent supplanter afin de
fournir un B à A. Ok ? Bien.
Dans l'exemple ci-dessus, const GetName() qui appelle non const GetB() ne
vous aura pas échappé. Et voilà mon problème. Actuellement je contourne ça
ainsi :
protected:
virtual B & GetB() = 0;
virtual const B & GetB() const = 0;
};
Mais j'aimerais bien arriver à frabriquer l'accesseur const à partir du non
const et ainsi réduire le nombre de fonctions virtuelles pures (qui sont
identiques ici vu de la classe fille). Est-ce possible (propement, sans
const_cast, à moins qu'il soit justifié) ?
Merci.
class A { public: string GetName() const { return this->GetB().GetName(); } protected: virtual B & GetB() = 0; }; [...]
Mais j'aimerais bien arriver à frabriquer l'accesseur const à partir du non const et ainsi réduire le nombre de fonctions virtuelles pures (qui sont identiques ici vu de la classe fille). Est-ce possible (propement, sans const_cast, à moins qu'il soit justifié) ?
Qu'appelles-tu un const_cast justifié ? De deux choses l'une : 1) la fonction GetB() peut changer l'objet A Dans ce cas, il est logique de ne pas appeler GetB() dans une fonction const de A. 2) la fonction GetB() ne change pas l'objet A mais permet indirectement de le changer dans le cas où l'on change le B retourné par la fonction. Dans ce cas, si l'on n'appelle que des fonctions const sur B, alors on est assuré de ne pas changer A.
Mais par ailleurs, si quelqu'un peut fournir son propre GetB() pour une sous-classe, rien ne l'empêcherait de modifier l'objet dans un GetB() non const. Donc, il est loin d'être certain que ce soit la bonne solution.
-- Arnaud (Supprimez les geneurs pour me répondre)
Aurélien REGAT-BARREL wrote:
class A
{
public:
string GetName() const
{
return this->GetB().GetName();
}
protected:
virtual B & GetB() = 0;
};
[...]
Mais j'aimerais bien arriver à frabriquer l'accesseur const à partir du non
const et ainsi réduire le nombre de fonctions virtuelles pures (qui sont
identiques ici vu de la classe fille). Est-ce possible (propement, sans
const_cast, à moins qu'il soit justifié) ?
Qu'appelles-tu un const_cast justifié ?
De deux choses l'une :
1) la fonction GetB() peut changer l'objet A
Dans ce cas, il est logique de ne pas appeler GetB() dans une
fonction const de A.
2) la fonction GetB() ne change pas l'objet A mais permet
indirectement de le changer dans le cas où l'on change le B retourné par
la fonction.
Dans ce cas, si l'on n'appelle que des fonctions const sur B, alors
on est assuré de ne pas changer A.
Mais par ailleurs, si quelqu'un peut fournir son propre GetB() pour une
sous-classe, rien ne l'empêcherait de modifier l'objet dans un GetB()
non const. Donc, il est loin d'être certain que ce soit la bonne solution.
--
Arnaud
(Supprimez les geneurs pour me répondre)
class A { public: string GetName() const { return this->GetB().GetName(); } protected: virtual B & GetB() = 0; }; [...]
Mais j'aimerais bien arriver à frabriquer l'accesseur const à partir du non const et ainsi réduire le nombre de fonctions virtuelles pures (qui sont identiques ici vu de la classe fille). Est-ce possible (propement, sans const_cast, à moins qu'il soit justifié) ?
Qu'appelles-tu un const_cast justifié ? De deux choses l'une : 1) la fonction GetB() peut changer l'objet A Dans ce cas, il est logique de ne pas appeler GetB() dans une fonction const de A. 2) la fonction GetB() ne change pas l'objet A mais permet indirectement de le changer dans le cas où l'on change le B retourné par la fonction. Dans ce cas, si l'on n'appelle que des fonctions const sur B, alors on est assuré de ne pas changer A.
Mais par ailleurs, si quelqu'un peut fournir son propre GetB() pour une sous-classe, rien ne l'empêcherait de modifier l'objet dans un GetB() non const. Donc, il est loin d'être certain que ce soit la bonne solution.
-- Arnaud (Supprimez les geneurs pour me répondre)
Aurélien REGAT-BARREL
Qu'appelles-tu un const_cast justifié ? Ben j'ai tendance à considérer que tout ce qui est const_cast /
reinterpret_cast est généralement une marque de mauvaise conception (hormis contraintes telles que utilisation d'une lib c void *).
De deux choses l'une : 1) la fonction GetB() peut changer l'objet A Dans ce cas, il est logique de ne pas appeler GetB() dans une fonction const de A.
Non, c'est un stupide accesseur sur le B de la classe fille.
2) la fonction GetB() ne change pas l'objet A mais permet indirectement de le changer dans le cas où l'on change le B retourné par la fonction.
Oui. GetB renvoie simplement un B qui peut être modifié, et l'est à certains endroits. En fait au début j'étais parti sur un pointeur/référence que la classe fille devait passer au constructeur, et je me suis dit qu'ainsi c'était plus mieux bien :
class AImpl : public A { protected: B & GetB() { return this->b; }
private: BImpl b; };
Dans ce cas, si l'on n'appelle que des fonctions const sur B, alors on est assuré de ne pas changer A.
Pour éviter de pourrir de const_cast j'ai voulu surcharger GetB en const.
Mais par ailleurs, si quelqu'un peut fournir son propre GetB() pour une sous-classe, rien ne l'empêcherait de modifier l'objet dans un GetB() non const. Donc, il est loin d'être certain que ce soit la bonne solution.
Moui. En plus const_cast c'est pas beau :-)
-- Aurélien REGAT-BARREL
Qu'appelles-tu un const_cast justifié ?
Ben j'ai tendance à considérer que tout ce qui est const_cast /
reinterpret_cast est généralement une marque de mauvaise conception (hormis
contraintes telles que utilisation d'une lib c void *).
De deux choses l'une :
1) la fonction GetB() peut changer l'objet A
Dans ce cas, il est logique de ne pas appeler GetB() dans une
fonction const de A.
Non, c'est un stupide accesseur sur le B de la classe fille.
2) la fonction GetB() ne change pas l'objet A mais permet
indirectement de le changer dans le cas où l'on change le B retourné par
la fonction.
Oui. GetB renvoie simplement un B qui peut être modifié, et l'est à certains
endroits. En fait au début j'étais parti sur un pointeur/référence que la
classe fille devait passer au constructeur, et je me suis dit qu'ainsi
c'était plus mieux bien :
class AImpl : public A
{
protected:
B & GetB() { return this->b; }
private:
BImpl b;
};
Dans ce cas, si l'on n'appelle que des fonctions const sur B, alors
on est assuré de ne pas changer A.
Pour éviter de pourrir de const_cast j'ai voulu surcharger GetB en const.
Mais par ailleurs, si quelqu'un peut fournir son propre GetB() pour une
sous-classe, rien ne l'empêcherait de modifier l'objet dans un GetB()
non const. Donc, il est loin d'être certain que ce soit la bonne solution.
Qu'appelles-tu un const_cast justifié ? Ben j'ai tendance à considérer que tout ce qui est const_cast /
reinterpret_cast est généralement une marque de mauvaise conception (hormis contraintes telles que utilisation d'une lib c void *).
De deux choses l'une : 1) la fonction GetB() peut changer l'objet A Dans ce cas, il est logique de ne pas appeler GetB() dans une fonction const de A.
Non, c'est un stupide accesseur sur le B de la classe fille.
2) la fonction GetB() ne change pas l'objet A mais permet indirectement de le changer dans le cas où l'on change le B retourné par la fonction.
Oui. GetB renvoie simplement un B qui peut être modifié, et l'est à certains endroits. En fait au début j'étais parti sur un pointeur/référence que la classe fille devait passer au constructeur, et je me suis dit qu'ainsi c'était plus mieux bien :
class AImpl : public A { protected: B & GetB() { return this->b; }
private: BImpl b; };
Dans ce cas, si l'on n'appelle que des fonctions const sur B, alors on est assuré de ne pas changer A.
Pour éviter de pourrir de const_cast j'ai voulu surcharger GetB en const.
Mais par ailleurs, si quelqu'un peut fournir son propre GetB() pour une sous-classe, rien ne l'empêcherait de modifier l'objet dans un GetB() non const. Donc, il est loin d'être certain que ce soit la bonne solution.
Moui. En plus const_cast c'est pas beau :-)
-- Aurélien REGAT-BARREL
Loïc Joly
Aurélien REGAT-BARREL wrote:
Bonjour à tous, je cherche à appeler explicitement la version const d'une fonction membre. [...]
virtual B & GetB() = 0; virtual const B & GetB() const = 0;
Mais j'aimerais bien arriver à frabriquer l'accesseur const à partir du non const et ainsi réduire le nombre de fonctions virtuelles pures (qui sont identiques ici vu de la classe fille). Est-ce possible (propement, sans const_cast, à moins qu'il soit justifié) ?
Est-ce que le code suivant répond à ton problème ?
class B;
class A { public: B* getB() {return doGetB();} B const *getB() const {return doGetB();} private: virtual B* doGetB() const = 0; };
-- Loïc
Aurélien REGAT-BARREL wrote:
Bonjour à tous,
je cherche à appeler explicitement la version const d'une fonction membre.
[...]
virtual B & GetB() = 0;
virtual const B & GetB() const = 0;
Mais j'aimerais bien arriver à frabriquer l'accesseur const à partir du non
const et ainsi réduire le nombre de fonctions virtuelles pures (qui sont
identiques ici vu de la classe fille). Est-ce possible (propement, sans
const_cast, à moins qu'il soit justifié) ?
Est-ce que le code suivant répond à ton problème ?
class B;
class A
{
public:
B* getB() {return doGetB();}
B const *getB() const {return doGetB();}
private:
virtual B* doGetB() const = 0;
};
Bonjour à tous, je cherche à appeler explicitement la version const d'une fonction membre. [...]
virtual B & GetB() = 0; virtual const B & GetB() const = 0;
Mais j'aimerais bien arriver à frabriquer l'accesseur const à partir du non const et ainsi réduire le nombre de fonctions virtuelles pures (qui sont identiques ici vu de la classe fille). Est-ce possible (propement, sans const_cast, à moins qu'il soit justifié) ?
Est-ce que le code suivant répond à ton problème ?
class B;
class A { public: B* getB() {return doGetB();} B const *getB() const {return doGetB();} private: virtual B* doGetB() const = 0; };
-- Loïc
kanze
"Aurélien REGAT-BARREL" wrote in message news:<41a3428f$0$31404$...
je cherche à appeler explicitement la version const d'une fonction membre. C'est un cas un peu tordu que je résume ici: J'ai 2 classes abstraites A et B, A utilise B, mais B est fournie par une class B
{ public: virtual string GetName() const = 0; };
class A { public: string GetName() const { return this->GetB().GetName(); }
protected: virtual B & GetB() = 0; };
GetB() est la fonction que les classes filles doivent supplanter afin de fournir un B à A. Ok ? Bien.
Dans l'exemple ci-dessus, const GetName() qui appelle non const GetB() ne vous aura pas échappé. Et voilà mon problème. Actuellement je contourne ça ainsi :
protected: virtual B & GetB() = 0; virtual const B & GetB() const = 0; };
Mais j'aimerais bien arriver à frabriquer l'accesseur const à partir du non const et ainsi réduire le nombre de fonctions virtuelles pures (qui sont identiques ici vu de la classe fille). Est-ce possible (propement, sans const_cast, à moins qu'il soit justifié) ?
La première question concerne le B, qui est bien un objet distinct de A. Est-ce qu'il y a une raison pour ne pas avoir simplement la seule fonction :
virtual B& GetB() const = 0 ;
Ensuite, il faut poser la question que fait GetB ? Est-ce qu'il est vraiment genant qu'elle existe en deux versions (comme tu fait maintenant.)
-- James Kanze GABI Software http://www.gabi-soft.fr Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
"Aurélien REGAT-BARREL" <nospam-aregatba@yahoo.fr.invalid> wrote in
message news:<41a3428f$0$31404$626a14ce@news.free.fr>...
je cherche à appeler explicitement la version const d'une fonction
membre. C'est un cas un peu tordu que je résume ici:
J'ai 2 classes abstraites A et B, A utilise B, mais B est fournie par
une class B
{
public:
virtual string GetName() const = 0;
};
class A
{
public:
string GetName() const
{
return this->GetB().GetName();
}
protected:
virtual B & GetB() = 0;
};
GetB() est la fonction que les classes filles doivent supplanter afin
de fournir un B à A. Ok ? Bien.
Dans l'exemple ci-dessus, const GetName() qui appelle non const GetB()
ne vous aura pas échappé. Et voilà mon problème. Actuellement je
contourne ça ainsi :
protected:
virtual B & GetB() = 0;
virtual const B & GetB() const = 0;
};
Mais j'aimerais bien arriver à frabriquer l'accesseur const à partir
du non const et ainsi réduire le nombre de fonctions virtuelles pures
(qui sont identiques ici vu de la classe fille). Est-ce possible
(propement, sans const_cast, à moins qu'il soit justifié) ?
La première question concerne le B, qui est bien un objet distinct de A.
Est-ce qu'il y a une raison pour ne pas avoir simplement la seule
fonction :
virtual B& GetB() const = 0 ;
Ensuite, il faut poser la question que fait GetB ? Est-ce qu'il est
vraiment genant qu'elle existe en deux versions (comme tu fait
maintenant.)
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
"Aurélien REGAT-BARREL" wrote in message news:<41a3428f$0$31404$...
je cherche à appeler explicitement la version const d'une fonction membre. C'est un cas un peu tordu que je résume ici: J'ai 2 classes abstraites A et B, A utilise B, mais B est fournie par une class B
{ public: virtual string GetName() const = 0; };
class A { public: string GetName() const { return this->GetB().GetName(); }
protected: virtual B & GetB() = 0; };
GetB() est la fonction que les classes filles doivent supplanter afin de fournir un B à A. Ok ? Bien.
Dans l'exemple ci-dessus, const GetName() qui appelle non const GetB() ne vous aura pas échappé. Et voilà mon problème. Actuellement je contourne ça ainsi :
protected: virtual B & GetB() = 0; virtual const B & GetB() const = 0; };
Mais j'aimerais bien arriver à frabriquer l'accesseur const à partir du non const et ainsi réduire le nombre de fonctions virtuelles pures (qui sont identiques ici vu de la classe fille). Est-ce possible (propement, sans const_cast, à moins qu'il soit justifié) ?
La première question concerne le B, qui est bien un objet distinct de A. Est-ce qu'il y a une raison pour ne pas avoir simplement la seule fonction :
virtual B& GetB() const = 0 ;
Ensuite, il faut poser la question que fait GetB ? Est-ce qu'il est vraiment genant qu'elle existe en deux versions (comme tu fait maintenant.)
-- James Kanze GABI Software http://www.gabi-soft.fr Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Falk Tannhäuser
wrote:
La première question concerne le B, qui est bien un objet distinct de A. Est-ce qu'il y a une raison pour ne pas avoir simplement la seule fonction :
virtual B& GetB() const = 0 ;
Effectivement, si l'état du B retourné par référence ne fait pas partie de l'état observable de l'objet de classe A sur lequel GetB() est appel ée, ça me paraît la bonne solution.
Au cas contraire, il faut réellement deux fonctions, et il me paraît le plus judicieux d'implémenter la version non-const en se servant de la version const :
virtual B const& GetB() const = 0;
B& GetB() // non virtuelle { A const* const_this = this; return const_cast<B&>(const_this->GetB()); // On pourrait écrire cela en une seule ligne mais c'est moins joli : //return const_cast<B&>(const_cast<A const*>(this)->GetB()); }
Ici, le const_cast me semble pleinement "justifie" : La version non-const de GetB() ne peut être appelée que sur un objet A non-const (sauf const_cast de la part de l'utilisateur), et l'objet B fait, au moins d'un point vu logique, partie de l'objet A. Il est donc lui aussi non-const, et par conséquent, on a le droit de le modifier après avoir crée un chemin d'accès non-const (moyennement const_cas t<B&)(...)).
Reste à savoir quel est réellement le type d'association entre l'obje t A et l'objet B retourné par A::GetB() - ce qui est une question de conceptio n plutôt que de C++, et seul l'OP saura y répondre.
Falk
kanze@gabi-soft.fr wrote:
La première question concerne le B, qui est bien un objet distinct de A.
Est-ce qu'il y a une raison pour ne pas avoir simplement la seule
fonction :
virtual B& GetB() const = 0 ;
Effectivement, si l'état du B retourné par référence ne fait pas partie
de l'état observable de l'objet de classe A sur lequel GetB() est appel ée,
ça me paraît la bonne solution.
Au cas contraire, il faut réellement deux fonctions, et il me paraît le
plus judicieux d'implémenter la version non-const en se servant de la
version const :
virtual B const& GetB() const = 0;
B& GetB() // non virtuelle
{
A const* const_this = this;
return const_cast<B&>(const_this->GetB());
// On pourrait écrire cela en une seule ligne mais c'est moins joli :
//return const_cast<B&>(const_cast<A const*>(this)->GetB());
}
Ici, le const_cast me semble pleinement "justifie" :
La version non-const de GetB() ne peut être appelée que sur un objet A
non-const (sauf const_cast de la part de l'utilisateur), et l'objet B
fait, au moins d'un point vu logique, partie de l'objet A. Il est donc
lui aussi non-const, et par conséquent, on a le droit de le modifier
après avoir crée un chemin d'accès non-const (moyennement const_cas t<B&)(...)).
Reste à savoir quel est réellement le type d'association entre l'obje t A et
l'objet B retourné par A::GetB() - ce qui est une question de conceptio n
plutôt que de C++, et seul l'OP saura y répondre.
La première question concerne le B, qui est bien un objet distinct de A. Est-ce qu'il y a une raison pour ne pas avoir simplement la seule fonction :
virtual B& GetB() const = 0 ;
Effectivement, si l'état du B retourné par référence ne fait pas partie de l'état observable de l'objet de classe A sur lequel GetB() est appel ée, ça me paraît la bonne solution.
Au cas contraire, il faut réellement deux fonctions, et il me paraît le plus judicieux d'implémenter la version non-const en se servant de la version const :
virtual B const& GetB() const = 0;
B& GetB() // non virtuelle { A const* const_this = this; return const_cast<B&>(const_this->GetB()); // On pourrait écrire cela en une seule ligne mais c'est moins joli : //return const_cast<B&>(const_cast<A const*>(this)->GetB()); }
Ici, le const_cast me semble pleinement "justifie" : La version non-const de GetB() ne peut être appelée que sur un objet A non-const (sauf const_cast de la part de l'utilisateur), et l'objet B fait, au moins d'un point vu logique, partie de l'objet A. Il est donc lui aussi non-const, et par conséquent, on a le droit de le modifier après avoir crée un chemin d'accès non-const (moyennement const_cas t<B&)(...)).
Reste à savoir quel est réellement le type d'association entre l'obje t A et l'objet B retourné par A::GetB() - ce qui est une question de conceptio n plutôt que de C++, et seul l'OP saura y répondre.
Falk
Aurélien REGAT-BARREL
La première question concerne le B, qui est bien un objet distinct de A. Est-ce qu'il y a une raison pour ne pas avoir simplement la seule fonction :
virtual B& GetB() const = 0 ;
Pas possible, car GetB() est supplantée de cette manière :
class A; // abstraite class B; // abstraite
class B1 : public B { };
class A_B1 : public A { protected: B & GetB() { return this->b; }
private: B1 b; // A_B2 utilise un B2 }
Pour info une classe A template c'est pas possible car je doit spécialiser A_Bx en fonction du Bx utilisé.
Ensuite, il faut poser la question que fait GetB ? Est-ce qu'il est vraiment genant qu'elle existe en deux versions (comme tu fait maintenant.)
GetB() sert juste à fournir à la classe de base le B utilisé par la classe fille. C'est pas la mort non. Gênant c'est le mot. Car en fait il y a plusieurs B dans A (de types possiblement différents, [possiblement ça existe ?]), et donc ça multiplie par deux le nombre de fonctions à supplanter, fonctions strictement identiques au const près. Donc je vis très bien avec mes deux fonctions, je voudrais juste quelque chose de plus élégant... Je pensais qu'il y avait une astuce. Etant donné qu'une fonction n'est pas constante car elle renvoie une donnée membre non constante, si on lui fait renvoyer cette même donnée membre constante je pensais naïvement qu'on pouvait la rendre constante. Mais vu que le compilo ne s'attache qu'à la signature d'une fonction et non à ce qu'elle fait, je réalise que c'est pas possible.
-- Aurélien REGAT-BARREL
La première question concerne le B, qui est bien un objet distinct de A.
Est-ce qu'il y a une raison pour ne pas avoir simplement la seule
fonction :
virtual B& GetB() const = 0 ;
Pas possible, car GetB() est supplantée de cette manière :
class A; // abstraite
class B; // abstraite
class B1 : public B
{
};
class A_B1 : public A
{
protected:
B & GetB() { return this->b; }
private:
B1 b; // A_B2 utilise un B2
}
Pour info une classe A template c'est pas possible car je doit spécialiser
A_Bx en fonction du Bx utilisé.
Ensuite, il faut poser la question que fait GetB ? Est-ce qu'il est
vraiment genant qu'elle existe en deux versions (comme tu fait
maintenant.)
GetB() sert juste à fournir à la classe de base le B utilisé par la classe
fille.
C'est pas la mort non. Gênant c'est le mot. Car en fait il y a plusieurs B
dans A (de types possiblement différents, [possiblement ça existe ?]), et
donc ça multiplie par deux le nombre de fonctions à supplanter, fonctions
strictement identiques au const près.
Donc je vis très bien avec mes deux fonctions, je voudrais juste quelque
chose de plus élégant...
Je pensais qu'il y avait une astuce. Etant donné qu'une fonction n'est pas
constante car elle renvoie une donnée membre non constante, si on lui fait
renvoyer cette même donnée membre constante je pensais naïvement qu'on
pouvait la rendre constante. Mais vu que le compilo ne s'attache qu'à la
signature d'une fonction et non à ce qu'elle fait, je réalise que c'est pas
possible.
La première question concerne le B, qui est bien un objet distinct de A. Est-ce qu'il y a une raison pour ne pas avoir simplement la seule fonction :
virtual B& GetB() const = 0 ;
Pas possible, car GetB() est supplantée de cette manière :
class A; // abstraite class B; // abstraite
class B1 : public B { };
class A_B1 : public A { protected: B & GetB() { return this->b; }
private: B1 b; // A_B2 utilise un B2 }
Pour info une classe A template c'est pas possible car je doit spécialiser A_Bx en fonction du Bx utilisé.
Ensuite, il faut poser la question que fait GetB ? Est-ce qu'il est vraiment genant qu'elle existe en deux versions (comme tu fait maintenant.)
GetB() sert juste à fournir à la classe de base le B utilisé par la classe fille. C'est pas la mort non. Gênant c'est le mot. Car en fait il y a plusieurs B dans A (de types possiblement différents, [possiblement ça existe ?]), et donc ça multiplie par deux le nombre de fonctions à supplanter, fonctions strictement identiques au const près. Donc je vis très bien avec mes deux fonctions, je voudrais juste quelque chose de plus élégant... Je pensais qu'il y avait une astuce. Etant donné qu'une fonction n'est pas constante car elle renvoie une donnée membre non constante, si on lui fait renvoyer cette même donnée membre constante je pensais naïvement qu'on pouvait la rendre constante. Mais vu que le compilo ne s'attache qu'à la signature d'une fonction et non à ce qu'elle fait, je réalise que c'est pas possible.
-- Aurélien REGAT-BARREL
Aurélien REGAT-BARREL
virtual B& GetB() const = 0 ;
Effectivement, si l'état du B retourné par référence ne fait pas partie de l'état observable de l'objet de classe A sur lequel GetB() est appelée, ça me paraît la bonne solution.
Sauf que B en fait partie :-/
Au cas contraire, il faut réellement deux fonctions, et il me paraît le plus judicieux d'implémenter la version non-const en se servant de la version const :
Je pensais faire le contraire : implémenter le const à partir du non const. Cela me parraît dangereux de casser ce const. Vu de la classe fille on pourrait croire que GetB() ne modifie pas le B fourni. Hors tralala c'est le cas. Dans l'autre sens on ne fait que forcer le compilateur à considérer une fonction membre comme const, chose qu'elle est effectivement.
La version non-const de GetB() ne peut être appelée que sur un objet A non-const (sauf const_cast de la part de l'utilisateur), et l'objet B fait, au moins d'un point vu logique, partie de l'objet A. Il est donc lui aussi non-const, et par conséquent, on a le droit de le modifier après avoir crée un chemin d'accès non-const (moyennement const_cast<B&)(...)).
Je vois ce que tu veux dire. Comme non const GetB est appelé sur un A qui doit être non const (et qui est donc modifiable), on a le droit au const_cast. Le problème c'est que le B est possédé par une classe fille, et vue de celle-ci elle donne accès à sa classe mère un accès en lecture seule à sa donnée membre. Hors la classe mère a bel et bien besoin de modifier le B donné.
En fait, je cherche en quelque sorte à avoir une donnée membre virtuelle pure :-)
-- Aurélien REGAT-BARREL
virtual B& GetB() const = 0 ;
Effectivement, si l'état du B retourné par référence ne fait pas partie
de l'état observable de l'objet de classe A sur lequel GetB() est appelée,
ça me paraît la bonne solution.
Sauf que B en fait partie :-/
Au cas contraire, il faut réellement deux fonctions, et il me paraît le
plus judicieux d'implémenter la version non-const en se servant de la
version const :
Je pensais faire le contraire : implémenter le const à partir du non const.
Cela me parraît dangereux de casser ce const. Vu de la classe fille on
pourrait croire que GetB() ne modifie pas le B fourni. Hors tralala c'est le
cas.
Dans l'autre sens on ne fait que forcer le compilateur à considérer une
fonction membre comme const, chose qu'elle est effectivement.
La version non-const de GetB() ne peut être appelée que sur un objet A
non-const (sauf const_cast de la part de l'utilisateur), et l'objet B
fait, au moins d'un point vu logique, partie de l'objet A. Il est donc
lui aussi non-const, et par conséquent, on a le droit de le modifier
après avoir crée un chemin d'accès non-const (moyennement
const_cast<B&)(...)).
Je vois ce que tu veux dire.
Comme non const GetB est appelé sur un A qui doit être non const (et qui est
donc modifiable),
on a le droit au const_cast.
Le problème c'est que le B est possédé par une classe fille, et vue de
celle-ci elle donne accès à sa classe mère un accès en lecture seule à sa
donnée membre. Hors la classe mère a bel et bien besoin de modifier le B
donné.
En fait, je cherche en quelque sorte à avoir une donnée membre virtuelle
pure :-)
Effectivement, si l'état du B retourné par référence ne fait pas partie de l'état observable de l'objet de classe A sur lequel GetB() est appelée, ça me paraît la bonne solution.
Sauf que B en fait partie :-/
Au cas contraire, il faut réellement deux fonctions, et il me paraît le plus judicieux d'implémenter la version non-const en se servant de la version const :
Je pensais faire le contraire : implémenter le const à partir du non const. Cela me parraît dangereux de casser ce const. Vu de la classe fille on pourrait croire que GetB() ne modifie pas le B fourni. Hors tralala c'est le cas. Dans l'autre sens on ne fait que forcer le compilateur à considérer une fonction membre comme const, chose qu'elle est effectivement.
La version non-const de GetB() ne peut être appelée que sur un objet A non-const (sauf const_cast de la part de l'utilisateur), et l'objet B fait, au moins d'un point vu logique, partie de l'objet A. Il est donc lui aussi non-const, et par conséquent, on a le droit de le modifier après avoir crée un chemin d'accès non-const (moyennement const_cast<B&)(...)).
Je vois ce que tu veux dire. Comme non const GetB est appelé sur un A qui doit être non const (et qui est donc modifiable), on a le droit au const_cast. Le problème c'est que le B est possédé par une classe fille, et vue de celle-ci elle donne accès à sa classe mère un accès en lecture seule à sa donnée membre. Hors la classe mère a bel et bien besoin de modifier le B donné.
En fait, je cherche en quelque sorte à avoir une donnée membre virtuelle pure :-)
-- Aurélien REGAT-BARREL
Aurélien REGAT-BARREL
Est-ce que le code suivant répond à ton problème ?
class B;
class A { public: B* getB() {return doGetB();} B const *getB() const {return doGetB();} private: virtual B* doGetB() const = 0; };
Si je peux écrire doGetB const qui me renvoie un B non const, plus besoin de doGetB(), j'ai mon GetB() ;-) C'est le doGetB() que je cherche à avoir, avec le B renvoyé membre de la classe fille de A.
-- Aurélien REGAT-BARREL
Est-ce que le code suivant répond à ton problème ?
class B;
class A
{
public:
B* getB() {return doGetB();}
B const *getB() const {return doGetB();}
private:
virtual B* doGetB() const = 0;
};
Si je peux écrire doGetB const qui me renvoie un B non const, plus besoin de
doGetB(), j'ai mon GetB() ;-)
C'est le doGetB() que je cherche à avoir, avec le B renvoyé membre de la
classe fille de A.
Est-ce que le code suivant répond à ton problème ?
class B;
class A { public: B* getB() {return doGetB();} B const *getB() const {return doGetB();} private: virtual B* doGetB() const = 0; };
Si je peux écrire doGetB const qui me renvoie un B non const, plus besoin de doGetB(), j'ai mon GetB() ;-) C'est le doGetB() que je cherche à avoir, avec le B renvoyé membre de la classe fille de A.
-- Aurélien REGAT-BARREL
drkm
"Aurélien REGAT-BARREL" writes:
Est-ce que le code suivant répond à ton problème ?
class B;
class A { public: B* getB() {return doGetB();} B const *getB() const {return doGetB();} private: virtual B* doGetB() const = 0; };
Si je peux écrire doGetB const qui me renvoie un B non const, plus besoin de doGetB(), j'ai mon GetB() ;-) C'est le doGetB() que je cherche à avoir, avec le B renvoyé membre de la classe fille de A.
Donc, tu veux modifier une variable membre d'un objet constant ?
Est-ce que le code suivant répond à ton problème ?
class B;
class A
{
public:
B* getB() {return doGetB();}
B const *getB() const {return doGetB();}
private:
virtual B* doGetB() const = 0;
};
Si je peux écrire doGetB const qui me renvoie un B non const, plus besoin de
doGetB(), j'ai mon GetB() ;-)
C'est le doGetB() que je cherche à avoir, avec le B renvoyé membre de la
classe fille de A.
Donc, tu veux modifier une variable membre d'un objet constant ?
Est-ce que le code suivant répond à ton problème ?
class B;
class A { public: B* getB() {return doGetB();} B const *getB() const {return doGetB();} private: virtual B* doGetB() const = 0; };
Si je peux écrire doGetB const qui me renvoie un B non const, plus besoin de doGetB(), j'ai mon GetB() ;-) C'est le doGetB() que je cherche à avoir, avec le B renvoyé membre de la classe fille de A.
Donc, tu veux modifier une variable membre d'un objet constant ?
--drkm
Loïc Joly
Aurélien REGAT-BARREL wrote:
Est-ce que le code suivant répond à ton problème ?
class B;
class A { public: B* getB() {return doGetB();} B const *getB() const {return doGetB();} private: virtual B* doGetB() const = 0; };
Si je peux écrire doGetB const qui me renvoie un B non const, plus besoin de doGetB(), j'ai mon GetB() ;-)
Pas tout à fait. Implémenter un tel doGetB est facile (il suffit que B soit inclu par un pointeur dans le dérivé de A). Mais un tel doGetB viole la const correctness "philosophique" de la classe, d'où l'intérêt de l'encapsuler dans deux fonctions qui rétablissent cette const-correctness.
Le code suivant compile :
class B{};
class A { public: B* getB() {return doGetB();} B const *getB() const {return doGetB();} private: virtual B* doGetB() const = 0; };
class A1 : public A { private: virtual B* doGetB() const {return myB;} B *myB; };
int main() { A* a = new A1; A const * ac = new A1; B* b = a->getB(); B const *bc = ac->getB(); }
-- Loïc
Aurélien REGAT-BARREL wrote:
Est-ce que le code suivant répond à ton problème ?
class B;
class A
{
public:
B* getB() {return doGetB();}
B const *getB() const {return doGetB();}
private:
virtual B* doGetB() const = 0;
};
Si je peux écrire doGetB const qui me renvoie un B non const, plus besoin de
doGetB(), j'ai mon GetB() ;-)
Pas tout à fait. Implémenter un tel doGetB est facile (il suffit que B
soit inclu par un pointeur dans le dérivé de A). Mais un tel doGetB
viole la const correctness "philosophique" de la classe, d'où l'intérêt
de l'encapsuler dans deux fonctions qui rétablissent cette
const-correctness.
Le code suivant compile :
class B{};
class A
{
public:
B* getB() {return doGetB();}
B const *getB() const {return doGetB();}
private:
virtual B* doGetB() const = 0;
};
class A1 : public A
{
private:
virtual B* doGetB() const {return myB;}
B *myB;
};
int main()
{
A* a = new A1;
A const * ac = new A1;
B* b = a->getB();
B const *bc = ac->getB();
}
Est-ce que le code suivant répond à ton problème ?
class B;
class A { public: B* getB() {return doGetB();} B const *getB() const {return doGetB();} private: virtual B* doGetB() const = 0; };
Si je peux écrire doGetB const qui me renvoie un B non const, plus besoin de doGetB(), j'ai mon GetB() ;-)
Pas tout à fait. Implémenter un tel doGetB est facile (il suffit que B soit inclu par un pointeur dans le dérivé de A). Mais un tel doGetB viole la const correctness "philosophique" de la classe, d'où l'intérêt de l'encapsuler dans deux fonctions qui rétablissent cette const-correctness.
Le code suivant compile :
class B{};
class A { public: B* getB() {return doGetB();} B const *getB() const {return doGetB();} private: virtual B* doGetB() const = 0; };
class A1 : public A { private: virtual B* doGetB() const {return myB;} B *myB; };
int main() { A* a = new A1; A const * ac = new A1; B* b = a->getB(); B const *bc = ac->getB(); }