voilà, j'ai une petite question qui intervient quand on
cherche par exemple à faire une factory.
Si une classe B dérive d'une classe A, pourquoi le compilo ne réussit-
il pas à caster seul
un pointeur sur la fonction suivante :
B* f() { return new B(); };
en un A* (*)(void) ?
Dans la mesure où B dérive de A, la conversion paraît simple, non ?
Toutefois, un reinterpret_cast semble fonctionner.
voilà, j'ai une petite question qui intervient quand on
cherche par exemple à faire une factory.
Si une classe B dérive d'une classe A, pourquoi le compilo ne réussit-
il pas à caster seul
un pointeur sur la fonction suivante :
B* f() { return new B(); };
en un A* (*)(void) ?
Dans la mesure où B dérive de A, la conversion paraît simple, non ?
Toutefois, un reinterpret_cast semble fonctionner.
voilà, j'ai une petite question qui intervient quand on
cherche par exemple à faire une factory.
Si une classe B dérive d'une classe A, pourquoi le compilo ne réussit-
il pas à caster seul
un pointeur sur la fonction suivante :
B* f() { return new B(); };
en un A* (*)(void) ?
Dans la mesure où B dérive de A, la conversion paraît simple, non ?
Toutefois, un reinterpret_cast semble fonctionner.
On Feb 12, 5:57 pm, ALB wrote:voilà, j'ai une petite question qui intervient quand on
cherche par exemple à faire une factory.
Si une classe B dérive d'une classe A, pourquoi le compilo ne réussi t-
il pas à caster seul
un pointeur sur la fonction suivante :
B* f() { return new B(); };
en un A* (*)(void) ?
Dans la mesure où B dérive de A, la conversion paraît simple, non ?
La conversion est simple. Utiliser le pointeur qui en résulte,
en revanche, a un comportement indéfini.Toutefois, un reinterpret_cast semble fonctionner.
Un des comportements possibles d'un comportement indéfini. Je
parie que tu n'as pas essayé toutes les possibilités.
Essaie par exemple :
#include <iostream>
class WrongBase
{
public:
virtual ~WrongBase() {}
virtual void g() const ;
} ;
void
WrongBase::g() const
{
std::cout << "in WrongBase::g()" << std::endl ;
}
class Base
{
public:
virtual ~Base() {}
virtual void f() const ;
} ;
void
Base::f() const
{
std::cout << "in Base::f()" << std::endl ;
}
class Derived : public WrongBase, public Base
{
virtual void f() const ;
} ;
void
Derived::f() const
{
std::cout << "In Derived:f()" << std::endl ;
}
Derived*
factoryDerived()
{
return new Derived ;
}
int
main()
{
Base* (* factory)()
= reinterpret_cast< Base* (*)() >( &factoryDeriv ed ) ;
Base* pBase = (*factory)() ;
pBase->f() ;
return 0 ;
}
Pas de problème à la compilation. Pas de crash non plus à
l'exécution. Mais la sortie n'est peut-être
pas tout à fait ce à laquelle on s'attendrait.
Dans d'autres cas, ça pourrait même provoquer un core dump.
--
James Kanze (GABI Software) email: l.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Date nverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
On Feb 12, 5:57 pm, ALB <lebatt...@crans.org> wrote:
voilà, j'ai une petite question qui intervient quand on
cherche par exemple à faire une factory.
Si une classe B dérive d'une classe A, pourquoi le compilo ne réussi t-
il pas à caster seul
un pointeur sur la fonction suivante :
B* f() { return new B(); };
en un A* (*)(void) ?
Dans la mesure où B dérive de A, la conversion paraît simple, non ?
La conversion est simple. Utiliser le pointeur qui en résulte,
en revanche, a un comportement indéfini.
Toutefois, un reinterpret_cast semble fonctionner.
Un des comportements possibles d'un comportement indéfini. Je
parie que tu n'as pas essayé toutes les possibilités.
Essaie par exemple :
#include <iostream>
class WrongBase
{
public:
virtual ~WrongBase() {}
virtual void g() const ;
} ;
void
WrongBase::g() const
{
std::cout << "in WrongBase::g()" << std::endl ;
}
class Base
{
public:
virtual ~Base() {}
virtual void f() const ;
} ;
void
Base::f() const
{
std::cout << "in Base::f()" << std::endl ;
}
class Derived : public WrongBase, public Base
{
virtual void f() const ;
} ;
void
Derived::f() const
{
std::cout << "In Derived:f()" << std::endl ;
}
Derived*
factoryDerived()
{
return new Derived ;
}
int
main()
{
Base* (* factory)()
= reinterpret_cast< Base* (*)() >( &factoryDeriv ed ) ;
Base* pBase = (*factory)() ;
pBase->f() ;
return 0 ;
}
Pas de problème à la compilation. Pas de crash non plus à
l'exécution. Mais la sortie n'est peut-être
pas tout à fait ce à laquelle on s'attendrait.
Dans d'autres cas, ça pourrait même provoquer un core dump.
--
James Kanze (GABI Software) email:james.ka...@gmai l.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Date nverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
On Feb 12, 5:57 pm, ALB wrote:voilà, j'ai une petite question qui intervient quand on
cherche par exemple à faire une factory.
Si une classe B dérive d'une classe A, pourquoi le compilo ne réussi t-
il pas à caster seul
un pointeur sur la fonction suivante :
B* f() { return new B(); };
en un A* (*)(void) ?
Dans la mesure où B dérive de A, la conversion paraît simple, non ?
La conversion est simple. Utiliser le pointeur qui en résulte,
en revanche, a un comportement indéfini.Toutefois, un reinterpret_cast semble fonctionner.
Un des comportements possibles d'un comportement indéfini. Je
parie que tu n'as pas essayé toutes les possibilités.
Essaie par exemple :
#include <iostream>
class WrongBase
{
public:
virtual ~WrongBase() {}
virtual void g() const ;
} ;
void
WrongBase::g() const
{
std::cout << "in WrongBase::g()" << std::endl ;
}
class Base
{
public:
virtual ~Base() {}
virtual void f() const ;
} ;
void
Base::f() const
{
std::cout << "in Base::f()" << std::endl ;
}
class Derived : public WrongBase, public Base
{
virtual void f() const ;
} ;
void
Derived::f() const
{
std::cout << "In Derived:f()" << std::endl ;
}
Derived*
factoryDerived()
{
return new Derived ;
}
int
main()
{
Base* (* factory)()
= reinterpret_cast< Base* (*)() >( &factoryDeriv ed ) ;
Base* pBase = (*factory)() ;
pBase->f() ;
return 0 ;
}
Pas de problème à la compilation. Pas de crash non plus à
l'exécution. Mais la sortie n'est peut-être
pas tout à fait ce à laquelle on s'attendrait.
Dans d'autres cas, ça pourrait même provoquer un core dump.
--
James Kanze (GABI Software) email: l.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Date nverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
On 12 fév, 19:44, James Kanze wrote:On Feb 12, 5:57 pm, ALB wrote:voilà, j'ai une petite question qui intervient quand on
cherche par exemple à faire une factory.
Si une classe B dérive d'une classe A, pourquoi le compilo ne réus sit-
il pas à caster seul
un pointeur sur la fonction suivante :
B* f() { return new B(); };
en un A* (*)(void) ?
Dans la mesure où B dérive de A, la conversion paraît simple, no n ?
La conversion est simple. Utiliser le pointeur qui en résulte,
en revanche, a un comportement indéfini.Toutefois, un reinterpret_cast semble fonctionner.
Bel exemple !... donc le reinterpret_cast ne fait pas ce que
j'espérais (on ne peut vraiment pas compter sur lui ...)... à moins de
mettre WrongBase en second...
D'ailleurs, la norme garantit-elle que WrongBase et Base soient
"identiques" en mémoire ?
Je ne comprends cependant toujours pas pourquoi la conversion
ne s'opère pas comme je le souhaite...
Il y a bien une alternative de ce genre :
struct wrapper {
virtual Base* operator()(void) = 0;
virtual ~wrapper() {};
};
template<class T>
struct Wrapper : wrapper {
typedef T* (*Tptr)(void);
explicit Wrapper(Tptr builder) : wrapper(), _builder(builder) {};
Base* operator()(void) { return static_cast<Base*>(_builder());};
Tptr _builder;
};
mais je trouve cela cher en lignes de code et cela revient,
plus ou moins automatiquement, à écrire deux fonctions, une
qui renvoie un Derived* et une autre qui renvoie un Base*.
D'ailleurs, dans un tel Wrapper, le compilo n'est pas capable
de déterminer T tout seul, pourquoi ?
Il n'est pourtant pas possible d'overloader uniquement le type
de retour d'une fonction ?
On 12 fév, 19:44, James Kanze <james.ka...@gmail.com> wrote:
On Feb 12, 5:57 pm, ALB <lebatt...@crans.org> wrote:
voilà, j'ai une petite question qui intervient quand on
cherche par exemple à faire une factory.
Si une classe B dérive d'une classe A, pourquoi le compilo ne réus sit-
il pas à caster seul
un pointeur sur la fonction suivante :
B* f() { return new B(); };
en un A* (*)(void) ?
Dans la mesure où B dérive de A, la conversion paraît simple, no n ?
La conversion est simple. Utiliser le pointeur qui en résulte,
en revanche, a un comportement indéfini.
Toutefois, un reinterpret_cast semble fonctionner.
Bel exemple !... donc le reinterpret_cast ne fait pas ce que
j'espérais (on ne peut vraiment pas compter sur lui ...)... à moins de
mettre WrongBase en second...
D'ailleurs, la norme garantit-elle que WrongBase et Base soient
"identiques" en mémoire ?
Je ne comprends cependant toujours pas pourquoi la conversion
ne s'opère pas comme je le souhaite...
Il y a bien une alternative de ce genre :
struct wrapper {
virtual Base* operator()(void) = 0;
virtual ~wrapper() {};
};
template<class T>
struct Wrapper : wrapper {
typedef T* (*Tptr)(void);
explicit Wrapper(Tptr builder) : wrapper(), _builder(builder) {};
Base* operator()(void) { return static_cast<Base*>(_builder());};
Tptr _builder;
};
mais je trouve cela cher en lignes de code et cela revient,
plus ou moins automatiquement, à écrire deux fonctions, une
qui renvoie un Derived* et une autre qui renvoie un Base*.
D'ailleurs, dans un tel Wrapper, le compilo n'est pas capable
de déterminer T tout seul, pourquoi ?
Il n'est pourtant pas possible d'overloader uniquement le type
de retour d'une fonction ?
On 12 fév, 19:44, James Kanze wrote:On Feb 12, 5:57 pm, ALB wrote:voilà, j'ai une petite question qui intervient quand on
cherche par exemple à faire une factory.
Si une classe B dérive d'une classe A, pourquoi le compilo ne réus sit-
il pas à caster seul
un pointeur sur la fonction suivante :
B* f() { return new B(); };
en un A* (*)(void) ?
Dans la mesure où B dérive de A, la conversion paraît simple, no n ?
La conversion est simple. Utiliser le pointeur qui en résulte,
en revanche, a un comportement indéfini.Toutefois, un reinterpret_cast semble fonctionner.
Bel exemple !... donc le reinterpret_cast ne fait pas ce que
j'espérais (on ne peut vraiment pas compter sur lui ...)... à moins de
mettre WrongBase en second...
D'ailleurs, la norme garantit-elle que WrongBase et Base soient
"identiques" en mémoire ?
Je ne comprends cependant toujours pas pourquoi la conversion
ne s'opère pas comme je le souhaite...
Il y a bien une alternative de ce genre :
struct wrapper {
virtual Base* operator()(void) = 0;
virtual ~wrapper() {};
};
template<class T>
struct Wrapper : wrapper {
typedef T* (*Tptr)(void);
explicit Wrapper(Tptr builder) : wrapper(), _builder(builder) {};
Base* operator()(void) { return static_cast<Base*>(_builder());};
Tptr _builder;
};
mais je trouve cela cher en lignes de code et cela revient,
plus ou moins automatiquement, à écrire deux fonctions, une
qui renvoie un Derived* et une autre qui renvoie un Base*.
D'ailleurs, dans un tel Wrapper, le compilo n'est pas capable
de déterminer T tout seul, pourquoi ?
Il n'est pourtant pas possible d'overloader uniquement le type
de retour d'une fonction ?
On Feb 12, 11:14 pm, ALB wrote:On 12 fév, 19:44, James Kanze wrote:On Feb 12, 5:57 pm, ALB wrote:voilà, j'ai une petite question qui intervient quand on
cherche par exemple à faire une factory.
Si une classe B dérive d'une classe A, pourquoi le compilo ne ré ussit-
il pas à caster seul
un pointeur sur la fonction suivante :
B* f() { return new B(); };
en un A* (*)(void) ?
Dans la mesure où B dérive de A, la conversion paraît simple, non ?
La conversion est simple. Utiliser le pointeur qui en résulte,
en revanche, a un comportement indéfini.Toutefois, un reinterpret_cast semble fonctionner.
Bel exemple !... donc le reinterpret_cast ne fait pas ce que
j'espérais (on ne peut vraiment pas compter sur lui ...)... à moins de
mettre WrongBase en second...
D'ailleurs, la norme garantit-elle que WrongBase et Base soient
"identiques" en mémoire ?
La norme ne dit rien sur les détails de l'implémentation. Une
implémentation est libre de disposer les éléments d'une classe
en mémoire comme il lui plaise, à très peu d'exceptions près.
Et l'organisation varie en fait d'un compilateur à l'autre.Je ne comprends cependant toujours pas pourquoi la conversion
ne s'opère pas comme je le souhaite...
Principalement pour deux raisons : d'une part, parce que ce
serait prèsqu'impossible à implémenter, ou en tout cas très
cher, et de l'autre parce qu'il n'a pas de sens.Il y a bien une alternative de ce genre :
struct wrapper {
virtual Base* operator()(void) = 0;
virtual ~wrapper() {};
};
template<class T>
struct Wrapper : wrapper {
typedef T* (*Tptr)(void);
explicit Wrapper(Tptr builder) : wrapper(), _builder(bui lder) {};
Base* operator()(void) { return static_cast<Base*>(_buil der());};
Tptr _builder;
};
mais je trouve cela cher en lignes de code et cela revient,
plus ou moins automatiquement, à écrire deux fonctions, une
qui renvoie un Derived* et une autre qui renvoie un Base*.
À la fin, il te faut bien deux fonctions, parce qu'il y a deux
fonctionalités distinctes. Obtenir un Base*, ce n'est pas
obtenir un Derived*.D'ailleurs, dans un tel Wrapper, le compilo n'est pas capable
de déterminer T tout seul, pourquoi ?
Et comment le ferait-il ? Et quel sens est-ce que ça aurait s'il
le pouvait ? Je ne vois toujours pas comment tu comptes
utiliser tout ça s'il fonctionnait.Il n'est pourtant pas possible d'overloader uniquement le type
de retour d'une fonction ?
Non. D'autre langages (par exemple l'Ada) le supportent, mais
ils n'ont pas toutes les conversions implicites de C++. En C++,
ça risquerait de provoquer plus de confusion qu'autre chose.
On peut le simuler dans des cas bien précis :
class Owner
{
public:
class Proxy
{
public:
explicit Proxy( Owner const* owner )
: myOwner( owner )
{
}
template< typename T >
operator T() const
{
return myOwner->typedGet< T >() ;
}
private:
Owner const* myOwner ;
} ;
// ...
Proxy get() const
{
return Proxy( this ) ;
}
template< typename T >
T typedGet() const
{
// ...
}
} ;
Dans la pratique, il n'y a pas autant de cas où c'est
raisonable. Les fonctions get ont dans la pratique des
paramètres pour choisir une attribute parmi d'autres, et il se
pose toujours la question que faire si l'attribute choisie ne se
converte pas au type choisi.
--
James Kanze (GABI Software) email: l.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Date nverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34- M asquer le texte des messages précédents -
- Afficher le texte des messages précédents -- Masquer le texte des me ssages précédents -
- Afficher le texte des messages précédents -
On Feb 12, 11:14 pm, ALB <lebatt...@crans.org> wrote:
On 12 fév, 19:44, James Kanze <james.ka...@gmail.com> wrote:
On Feb 12, 5:57 pm, ALB <lebatt...@crans.org> wrote:
voilà, j'ai une petite question qui intervient quand on
cherche par exemple à faire une factory.
Si une classe B dérive d'une classe A, pourquoi le compilo ne ré ussit-
il pas à caster seul
un pointeur sur la fonction suivante :
B* f() { return new B(); };
en un A* (*)(void) ?
Dans la mesure où B dérive de A, la conversion paraît simple, non ?
La conversion est simple. Utiliser le pointeur qui en résulte,
en revanche, a un comportement indéfini.
Toutefois, un reinterpret_cast semble fonctionner.
Bel exemple !... donc le reinterpret_cast ne fait pas ce que
j'espérais (on ne peut vraiment pas compter sur lui ...)... à moins de
mettre WrongBase en second...
D'ailleurs, la norme garantit-elle que WrongBase et Base soient
"identiques" en mémoire ?
La norme ne dit rien sur les détails de l'implémentation. Une
implémentation est libre de disposer les éléments d'une classe
en mémoire comme il lui plaise, à très peu d'exceptions près.
Et l'organisation varie en fait d'un compilateur à l'autre.
Je ne comprends cependant toujours pas pourquoi la conversion
ne s'opère pas comme je le souhaite...
Principalement pour deux raisons : d'une part, parce que ce
serait prèsqu'impossible à implémenter, ou en tout cas très
cher, et de l'autre parce qu'il n'a pas de sens.
Il y a bien une alternative de ce genre :
struct wrapper {
virtual Base* operator()(void) = 0;
virtual ~wrapper() {};
};
template<class T>
struct Wrapper : wrapper {
typedef T* (*Tptr)(void);
explicit Wrapper(Tptr builder) : wrapper(), _builder(bui lder) {};
Base* operator()(void) { return static_cast<Base*>(_buil der());};
Tptr _builder;
};
mais je trouve cela cher en lignes de code et cela revient,
plus ou moins automatiquement, à écrire deux fonctions, une
qui renvoie un Derived* et une autre qui renvoie un Base*.
À la fin, il te faut bien deux fonctions, parce qu'il y a deux
fonctionalités distinctes. Obtenir un Base*, ce n'est pas
obtenir un Derived*.
D'ailleurs, dans un tel Wrapper, le compilo n'est pas capable
de déterminer T tout seul, pourquoi ?
Et comment le ferait-il ? Et quel sens est-ce que ça aurait s'il
le pouvait ? Je ne vois toujours pas comment tu comptes
utiliser tout ça s'il fonctionnait.
Il n'est pourtant pas possible d'overloader uniquement le type
de retour d'une fonction ?
Non. D'autre langages (par exemple l'Ada) le supportent, mais
ils n'ont pas toutes les conversions implicites de C++. En C++,
ça risquerait de provoquer plus de confusion qu'autre chose.
On peut le simuler dans des cas bien précis :
class Owner
{
public:
class Proxy
{
public:
explicit Proxy( Owner const* owner )
: myOwner( owner )
{
}
template< typename T >
operator T() const
{
return myOwner->typedGet< T >() ;
}
private:
Owner const* myOwner ;
} ;
// ...
Proxy get() const
{
return Proxy( this ) ;
}
template< typename T >
T typedGet() const
{
// ...
}
} ;
Dans la pratique, il n'y a pas autant de cas où c'est
raisonable. Les fonctions get ont dans la pratique des
paramètres pour choisir une attribute parmi d'autres, et il se
pose toujours la question que faire si l'attribute choisie ne se
converte pas au type choisi.
--
James Kanze (GABI Software) email:james.ka...@gmai l.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Date nverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34- M asquer le texte des messages précédents -
- Afficher le texte des messages précédents -- Masquer le texte des me ssages précédents -
- Afficher le texte des messages précédents -
On Feb 12, 11:14 pm, ALB wrote:On 12 fév, 19:44, James Kanze wrote:On Feb 12, 5:57 pm, ALB wrote:voilà, j'ai une petite question qui intervient quand on
cherche par exemple à faire une factory.
Si une classe B dérive d'une classe A, pourquoi le compilo ne ré ussit-
il pas à caster seul
un pointeur sur la fonction suivante :
B* f() { return new B(); };
en un A* (*)(void) ?
Dans la mesure où B dérive de A, la conversion paraît simple, non ?
La conversion est simple. Utiliser le pointeur qui en résulte,
en revanche, a un comportement indéfini.Toutefois, un reinterpret_cast semble fonctionner.
Bel exemple !... donc le reinterpret_cast ne fait pas ce que
j'espérais (on ne peut vraiment pas compter sur lui ...)... à moins de
mettre WrongBase en second...
D'ailleurs, la norme garantit-elle que WrongBase et Base soient
"identiques" en mémoire ?
La norme ne dit rien sur les détails de l'implémentation. Une
implémentation est libre de disposer les éléments d'une classe
en mémoire comme il lui plaise, à très peu d'exceptions près.
Et l'organisation varie en fait d'un compilateur à l'autre.Je ne comprends cependant toujours pas pourquoi la conversion
ne s'opère pas comme je le souhaite...
Principalement pour deux raisons : d'une part, parce que ce
serait prèsqu'impossible à implémenter, ou en tout cas très
cher, et de l'autre parce qu'il n'a pas de sens.Il y a bien une alternative de ce genre :
struct wrapper {
virtual Base* operator()(void) = 0;
virtual ~wrapper() {};
};
template<class T>
struct Wrapper : wrapper {
typedef T* (*Tptr)(void);
explicit Wrapper(Tptr builder) : wrapper(), _builder(bui lder) {};
Base* operator()(void) { return static_cast<Base*>(_buil der());};
Tptr _builder;
};
mais je trouve cela cher en lignes de code et cela revient,
plus ou moins automatiquement, à écrire deux fonctions, une
qui renvoie un Derived* et une autre qui renvoie un Base*.
À la fin, il te faut bien deux fonctions, parce qu'il y a deux
fonctionalités distinctes. Obtenir un Base*, ce n'est pas
obtenir un Derived*.D'ailleurs, dans un tel Wrapper, le compilo n'est pas capable
de déterminer T tout seul, pourquoi ?
Et comment le ferait-il ? Et quel sens est-ce que ça aurait s'il
le pouvait ? Je ne vois toujours pas comment tu comptes
utiliser tout ça s'il fonctionnait.Il n'est pourtant pas possible d'overloader uniquement le type
de retour d'une fonction ?
Non. D'autre langages (par exemple l'Ada) le supportent, mais
ils n'ont pas toutes les conversions implicites de C++. En C++,
ça risquerait de provoquer plus de confusion qu'autre chose.
On peut le simuler dans des cas bien précis :
class Owner
{
public:
class Proxy
{
public:
explicit Proxy( Owner const* owner )
: myOwner( owner )
{
}
template< typename T >
operator T() const
{
return myOwner->typedGet< T >() ;
}
private:
Owner const* myOwner ;
} ;
// ...
Proxy get() const
{
return Proxy( this ) ;
}
template< typename T >
T typedGet() const
{
// ...
}
} ;
Dans la pratique, il n'y a pas autant de cas où c'est
raisonable. Les fonctions get ont dans la pratique des
paramètres pour choisir une attribute parmi d'autres, et il se
pose toujours la question que faire si l'attribute choisie ne se
converte pas au type choisi.
--
James Kanze (GABI Software) email: l.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Date nverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34- M asquer le texte des messages précédents -
- Afficher le texte des messages précédents -- Masquer le texte des me ssages précédents -
- Afficher le texte des messages précédents -
On 13 fév, 09:28, James Kanze wrote:On Feb 12, 11:14 pm, ALB wrote:
En fait, si j'ai bien compris, le C++ convertit (implicitement) que
des objets et pas des fonctions (on convertit les objets pour les
adapter à la fonction mais on ne peut pas convertir la fonction pour
l'adapter aux objets).
C'est pourquoi, mon histoire de conversion de fonction n'a pas
de sens. Comme tu l'indiques, il faut donc bien deux
fonctions une qui renvoie un Base* et une qui renvoie un
Derived*.
Le problème de reconnaissance du type de retour d'une fonction
par un template était dans ma compréhension un problème
similaire (mais effectivement sans lien direct avec le cas
d'une factory).
On 13 fév, 09:28, James Kanze <james.ka...@gmail.com> wrote:
On Feb 12, 11:14 pm, ALB <lebatt...@crans.org> wrote:
En fait, si j'ai bien compris, le C++ convertit (implicitement) que
des objets et pas des fonctions (on convertit les objets pour les
adapter à la fonction mais on ne peut pas convertir la fonction pour
l'adapter aux objets).
C'est pourquoi, mon histoire de conversion de fonction n'a pas
de sens. Comme tu l'indiques, il faut donc bien deux
fonctions une qui renvoie un Base* et une qui renvoie un
Derived*.
Le problème de reconnaissance du type de retour d'une fonction
par un template était dans ma compréhension un problème
similaire (mais effectivement sans lien direct avec le cas
d'une factory).
On 13 fév, 09:28, James Kanze wrote:On Feb 12, 11:14 pm, ALB wrote:
En fait, si j'ai bien compris, le C++ convertit (implicitement) que
des objets et pas des fonctions (on convertit les objets pour les
adapter à la fonction mais on ne peut pas convertir la fonction pour
l'adapter aux objets).
C'est pourquoi, mon histoire de conversion de fonction n'a pas
de sens. Comme tu l'indiques, il faut donc bien deux
fonctions une qui renvoie un Base* et une qui renvoie un
Derived*.
Le problème de reconnaissance du type de retour d'une fonction
par un template était dans ma compréhension un problème
similaire (mais effectivement sans lien direct avec le cas
d'une factory).