je trouve ce procédé génial, je vais m'efforcer d'entre trouver une
utilité ;-)
je trouve ce procédé génial, je vais m'efforcer d'entre trouver une
utilité ;-)
je trouve ce procédé génial, je vais m'efforcer d'entre trouver une
utilité ;-)
Bonjour à tous,
Je viens de réaliser qu'il était possible de faire de l'héritage entre
inner classes. Il y a même pleins de possibilités:
[pleins de possibilités]
je trouve ce procédé génial, je vais m'efforcer d'entre trouver une
utilité ;-)
Plus sérieusement, je ne l'ai jamais croisé, et m'en étonne. N'y a-t-il
pas de technique particulière qui l'utilise ? Un cas typique où ça se
révèle une solution élégante ?
Bonjour à tous,
Je viens de réaliser qu'il était possible de faire de l'héritage entre
inner classes. Il y a même pleins de possibilités:
[pleins de possibilités]
je trouve ce procédé génial, je vais m'efforcer d'entre trouver une
utilité ;-)
Plus sérieusement, je ne l'ai jamais croisé, et m'en étonne. N'y a-t-il
pas de technique particulière qui l'utilise ? Un cas typique où ça se
révèle une solution élégante ?
Bonjour à tous,
Je viens de réaliser qu'il était possible de faire de l'héritage entre
inner classes. Il y a même pleins de possibilités:
[pleins de possibilités]
je trouve ce procédé génial, je vais m'efforcer d'entre trouver une
utilité ;-)
Plus sérieusement, je ne l'ai jamais croisé, et m'en étonne. N'y a-t-il
pas de technique particulière qui l'utilise ? Un cas typique où ça se
révèle une solution élégante ?
Je viens de réaliser qu'il était possible de faire de
l'héritage entre inner classes.
Il y a même pleins de
possibilités:
class A
{
public:
class PublicInnerA {};
protected:
class ProtectedInnerA {};
};
class B : public A::PublicInnerA {};
class C : public A
{
class InnerC;
};
class C::InnerC : public A::ProtectedInnerA
{
};
je trouve ce procédé génial, je vais m'efforcer d'entre
trouver une utilité ;-)
Plus sérieusement, je ne l'ai jamais croisé, et m'en étonne.
N'y a-t-il pas de technique particulière qui l'utilise ? Un
cas typique où ça se révèle une solution élégante ?
Je viens de réaliser qu'il était possible de faire de
l'héritage entre inner classes.
Il y a même pleins de
possibilités:
class A
{
public:
class PublicInnerA {};
protected:
class ProtectedInnerA {};
};
class B : public A::PublicInnerA {};
class C : public A
{
class InnerC;
};
class C::InnerC : public A::ProtectedInnerA
{
};
je trouve ce procédé génial, je vais m'efforcer d'entre
trouver une utilité ;-)
Plus sérieusement, je ne l'ai jamais croisé, et m'en étonne.
N'y a-t-il pas de technique particulière qui l'utilise ? Un
cas typique où ça se révèle une solution élégante ?
Je viens de réaliser qu'il était possible de faire de
l'héritage entre inner classes.
Il y a même pleins de
possibilités:
class A
{
public:
class PublicInnerA {};
protected:
class ProtectedInnerA {};
};
class B : public A::PublicInnerA {};
class C : public A
{
class InnerC;
};
class C::InnerC : public A::ProtectedInnerA
{
};
je trouve ce procédé génial, je vais m'efforcer d'entre
trouver une utilité ;-)
Plus sérieusement, je ne l'ai jamais croisé, et m'en étonne.
N'y a-t-il pas de technique particulière qui l'utilise ? Un
cas typique où ça se révèle une solution élégante ?
je trouve ce procédé génial, je vais m'efforcer d'entre
trouver une utilité ;-)
Je dirais que c'est assez fréquent, même. Je ne crois pas avoir
fait une application qui ne s'en servait pas.
Je l'utilise beaucoup aussi dans des classes templatées un peu
complexe, de peu que la classe en question utilise des noeuds ou
d'autres classes « implémentation ». Il y a une classe de base
non templatée qui factorise la partie vraiment générique (c-à-d
qui ne dépend pas des paramètres d'instantiation du template).
Donc, par exemple, j'ai une classe :
class HashTableImpl
{
// ...
protected:
class Node
{
// ...
} ;
} ;
template< typename T >
class AssocArrayOf : public HashTableImpl
{
// ...
struct TypedNode : Node
{
T value ;
// ...
} ;
} ;
(Dans ce cas-ci, HashTableImpl contient toute la gestion du
table haché, mais compte sur la classe dérivée pour les
opérations qui dépend du type, comme calculer le hachage,
comparer deux valeurs pour égalité, ou créer et detruire les
noeuds.)Plus sérieusement, je ne l'ai jamais croisé, et m'en étonne.
C'est cependant une technique fréquente -- dans l'implémentation
des templates, pour éviter le code bloat, comme ci-dessus, mais
aussi pour des cas comme les Visitor, ou les Actions dans une
transaction.
je trouve ce procédé génial, je vais m'efforcer d'entre
trouver une utilité ;-)
Je dirais que c'est assez fréquent, même. Je ne crois pas avoir
fait une application qui ne s'en servait pas.
Je l'utilise beaucoup aussi dans des classes templatées un peu
complexe, de peu que la classe en question utilise des noeuds ou
d'autres classes « implémentation ». Il y a une classe de base
non templatée qui factorise la partie vraiment générique (c-à-d
qui ne dépend pas des paramètres d'instantiation du template).
Donc, par exemple, j'ai une classe :
class HashTableImpl
{
// ...
protected:
class Node
{
// ...
} ;
} ;
template< typename T >
class AssocArrayOf : public HashTableImpl
{
// ...
struct TypedNode : Node
{
T value ;
// ...
} ;
} ;
(Dans ce cas-ci, HashTableImpl contient toute la gestion du
table haché, mais compte sur la classe dérivée pour les
opérations qui dépend du type, comme calculer le hachage,
comparer deux valeurs pour égalité, ou créer et detruire les
noeuds.)
Plus sérieusement, je ne l'ai jamais croisé, et m'en étonne.
C'est cependant une technique fréquente -- dans l'implémentation
des templates, pour éviter le code bloat, comme ci-dessus, mais
aussi pour des cas comme les Visitor, ou les Actions dans une
transaction.
je trouve ce procédé génial, je vais m'efforcer d'entre
trouver une utilité ;-)
Je dirais que c'est assez fréquent, même. Je ne crois pas avoir
fait une application qui ne s'en servait pas.
Je l'utilise beaucoup aussi dans des classes templatées un peu
complexe, de peu que la classe en question utilise des noeuds ou
d'autres classes « implémentation ». Il y a une classe de base
non templatée qui factorise la partie vraiment générique (c-à-d
qui ne dépend pas des paramètres d'instantiation du template).
Donc, par exemple, j'ai une classe :
class HashTableImpl
{
// ...
protected:
class Node
{
// ...
} ;
} ;
template< typename T >
class AssocArrayOf : public HashTableImpl
{
// ...
struct TypedNode : Node
{
T value ;
// ...
} ;
} ;
(Dans ce cas-ci, HashTableImpl contient toute la gestion du
table haché, mais compte sur la classe dérivée pour les
opérations qui dépend du type, comme calculer le hachage,
comparer deux valeurs pour égalité, ou créer et detruire les
noeuds.)Plus sérieusement, je ne l'ai jamais croisé, et m'en étonne.
C'est cependant une technique fréquente -- dans l'implémentation
des templates, pour éviter le code bloat, comme ci-dessus, mais
aussi pour des cas comme les Visitor, ou les Actions dans une
transaction.
je trouve ce procédé génial, je vais m'efforcer d'entre trouver une
utilité ;-)
Barf... Une classe est une classe, qu'elle soit membre d'une autre
classe ou pas.
En pratique, s'il s'agit d'isoler des classes, les mettre dans un
namespace dédié est une solution au moins aussi fréquente (du moins
dans mon code) que les mettre comme classes membres.
je trouve ce procédé génial, je vais m'efforcer d'entre trouver une
utilité ;-)
Barf... Une classe est une classe, qu'elle soit membre d'une autre
classe ou pas.
En pratique, s'il s'agit d'isoler des classes, les mettre dans un
namespace dédié est une solution au moins aussi fréquente (du moins
dans mon code) que les mettre comme classes membres.
je trouve ce procédé génial, je vais m'efforcer d'entre trouver une
utilité ;-)
Barf... Une classe est une classe, qu'elle soit membre d'une autre
classe ou pas.
En pratique, s'il s'agit d'isoler des classes, les mettre dans un
namespace dédié est une solution au moins aussi fréquente (du moins
dans mon code) que les mettre comme classes membres.
Je l'ai dit, je m'efforce d'en trouver une utilité. Mais
typiquement, j'ai déjà écrit ce genre de code (en simplifié
toujours):
class Base
{
public:
int DoSomething()
{
return this->GetSomething1() + this->GetSomething2();
}
protected:
virtual int GetSomething1() = 0;
virtual int GetSomething2() = 0;
};
Isoler l'interface à implémenter dans une nested class ne serait-il p as
plus élégant ?
class Base
{
protected:
class BaseInterface
{
public:
virtual int GetSomething1() = 0;
virtual int GetSomething2() = 0;
};
public:
int DoSomething()
{
return i_->GetSomething1() + i_->GetSomething2();
}
protected:
Base( BaseInterface *I ) : i_( I ) {}
private:
BaseInterface *i_;
};
Je l'ai dit, je m'efforce d'en trouver une utilité. Mais
typiquement, j'ai déjà écrit ce genre de code (en simplifié
toujours):
class Base
{
public:
int DoSomething()
{
return this->GetSomething1() + this->GetSomething2();
}
protected:
virtual int GetSomething1() = 0;
virtual int GetSomething2() = 0;
};
Isoler l'interface à implémenter dans une nested class ne serait-il p as
plus élégant ?
class Base
{
protected:
class BaseInterface
{
public:
virtual int GetSomething1() = 0;
virtual int GetSomething2() = 0;
};
public:
int DoSomething()
{
return i_->GetSomething1() + i_->GetSomething2();
}
protected:
Base( BaseInterface *I ) : i_( I ) {}
private:
BaseInterface *i_;
};
Je l'ai dit, je m'efforce d'en trouver une utilité. Mais
typiquement, j'ai déjà écrit ce genre de code (en simplifié
toujours):
class Base
{
public:
int DoSomething()
{
return this->GetSomething1() + this->GetSomething2();
}
protected:
virtual int GetSomething1() = 0;
virtual int GetSomething2() = 0;
};
Isoler l'interface à implémenter dans une nested class ne serait-il p as
plus élégant ?
class Base
{
protected:
class BaseInterface
{
public:
virtual int GetSomething1() = 0;
virtual int GetSomething2() = 0;
};
public:
int DoSomething()
{
return i_->GetSomething1() + i_->GetSomething2();
}
protected:
Base( BaseInterface *I ) : i_( I ) {}
private:
BaseInterface *i_;
};
Modèle de template, contre modèle de stratégie. En général, je
préfère le modèle de stratégie, mais ce n'est pas une règle
absolue. Le modèle de template sert surtout quand tu as de bons
défauts, et donc une implémentation dans la classe de base.
Dans ces cas-là, souvent, on peut utiliser la classe de base
sans en dériver ; on n'en dérive que pour modifier le
comportement de base. (Ça arrive souvent dans les hiérarchies de
GUI.)
Si tu veux utiliser le polymorphisme dans le constructeur, il
n'y a que le modèle de stratégie qui marche. Et encore, il faut
faire gaffe à l'ordre d'initialisation, au moins que tu exiges
que la classe déléguée soit allouée dynamiquement, et libérée
dans le destructeur de la Base. (Dans ce cas-là, je suggèrerais
l'utilisation de std::auto_ptr, déjà comme paramètre au
constructeur de la classe de base.)
Modèle de template, contre modèle de stratégie. En général, je
préfère le modèle de stratégie, mais ce n'est pas une règle
absolue. Le modèle de template sert surtout quand tu as de bons
défauts, et donc une implémentation dans la classe de base.
Dans ces cas-là, souvent, on peut utiliser la classe de base
sans en dériver ; on n'en dérive que pour modifier le
comportement de base. (Ça arrive souvent dans les hiérarchies de
GUI.)
Si tu veux utiliser le polymorphisme dans le constructeur, il
n'y a que le modèle de stratégie qui marche. Et encore, il faut
faire gaffe à l'ordre d'initialisation, au moins que tu exiges
que la classe déléguée soit allouée dynamiquement, et libérée
dans le destructeur de la Base. (Dans ce cas-là, je suggèrerais
l'utilisation de std::auto_ptr, déjà comme paramètre au
constructeur de la classe de base.)
Modèle de template, contre modèle de stratégie. En général, je
préfère le modèle de stratégie, mais ce n'est pas une règle
absolue. Le modèle de template sert surtout quand tu as de bons
défauts, et donc une implémentation dans la classe de base.
Dans ces cas-là, souvent, on peut utiliser la classe de base
sans en dériver ; on n'en dérive que pour modifier le
comportement de base. (Ça arrive souvent dans les hiérarchies de
GUI.)
Si tu veux utiliser le polymorphisme dans le constructeur, il
n'y a que le modèle de stratégie qui marche. Et encore, il faut
faire gaffe à l'ordre d'initialisation, au moins que tu exiges
que la classe déléguée soit allouée dynamiquement, et libérée
dans le destructeur de la Base. (Dans ce cas-là, je suggèrerais
l'utilisation de std::auto_ptr, déjà comme paramètre au
constructeur de la classe de base.)
Je viens de réaliser qu'il était possible de faire de l'héritage entre
inner classes. Il y a même pleins de possibilités:
[...]
je trouve ce procédé génial, je vais m'efforcer d'entre trouver une
utilité ;-)
Plus sérieusement, je ne l'ai jamais croisé, et m'en étonne. N'y a-t-il
pas de technique particulière qui l'utilise ? Un cas typique où ça se
révèle une solution élégante ?
Je viens de réaliser qu'il était possible de faire de l'héritage entre
inner classes. Il y a même pleins de possibilités:
[...]
je trouve ce procédé génial, je vais m'efforcer d'entre trouver une
utilité ;-)
Plus sérieusement, je ne l'ai jamais croisé, et m'en étonne. N'y a-t-il
pas de technique particulière qui l'utilise ? Un cas typique où ça se
révèle une solution élégante ?
Je viens de réaliser qu'il était possible de faire de l'héritage entre
inner classes. Il y a même pleins de possibilités:
[...]
je trouve ce procédé génial, je vais m'efforcer d'entre trouver une
utilité ;-)
Plus sérieusement, je ne l'ai jamais croisé, et m'en étonne. N'y a-t-il
pas de technique particulière qui l'utilise ? Un cas typique où ça se
révèle une solution élégante ?
Comme ça, je pense aux mixin-layers (assimilables à du CRTP en couches) au
sujet desquels Smaragdakis a écrit une thèse, en 99, disponible sur le net.
Comme ça, je pense aux mixin-layers (assimilables à du CRTP en couches) au
sujet desquels Smaragdakis a écrit une thèse, en 99, disponible sur le net.
Comme ça, je pense aux mixin-layers (assimilables à du CRTP en couches) au
sujet desquels Smaragdakis a écrit une thèse, en 99, disponible sur le net.