Comment puis-je utiliser CRTP en C ++ pour éviter la surcharge des fonctions membres virtuelles?
Comment puis-je utiliser CRTP en C ++ pour éviter la surcharge des fonctions membres virtuelles?
Réponses:
Il y a deux manières.
Le premier consiste à spécifier l'interface de manière statique pour la structure des types:
template <class Derived>
struct base {
void foo() {
static_cast<Derived *>(this)->foo();
};
};
struct my_type : base<my_type> {
void foo(); // required to compile.
};
struct your_type : base<your_type> {
void foo(); // required to compile.
};
La seconde consiste à éviter l'utilisation de l'idiome de référence à la base ou de pointeur à la base et à effectuer le câblage au moment de la compilation. En utilisant la définition ci-dessus, vous pouvez avoir des fonctions de modèle qui ressemblent à celles-ci:
template <class T> // T is deduced at compile-time
void bar(base<T> & obj) {
obj.foo(); // will do static dispatch
}
struct not_derived_from_base { }; // notice, not derived from base
// ...
my_type my_instance;
your_type your_instance;
not_derived_from_base invalid_instance;
bar(my_instance); // will call my_instance.foo()
bar(your_instance); // will call your_instance.foo()
bar(invalid_instance); // compile error, cannot deduce correct overload
Ainsi, la combinaison de la définition de structure / interface et de la déduction de type au moment de la compilation dans vos fonctions vous permet de faire une distribution statique au lieu d'une distribution dynamique. C'est l'essence du polymorphisme statique.
not_derived_from_base
n'est pas dérivé de base
, ni dérivé de base
...
J'ai moi-même recherché des discussions décentes sur le CRTP. Techniques for Scientific C ++ de Todd Veldhuizen est une excellente ressource pour cela (1.3) et de nombreuses autres techniques avancées comme les modèles d'expression.
De plus, j'ai trouvé que vous pouviez lire la plupart des articles originaux de Coplien sur C ++ Gems dans Google Books. C'est peut-être toujours le cas.
dynamic_cast
de méthodes virtuelles.
J'ai dû chercher CRTP . Après avoir fait cela, cependant, j'ai trouvé des trucs sur le polymorphisme statique . Je soupçonne que c'est la réponse à votre question.
Il s'avère qu'ATL utilise ce modèle assez largement.
Cette réponse Wikipedia a tout ce dont vous avez besoin. À savoir:
template <class Derived> struct Base
{
void interface()
{
// ...
static_cast<Derived*>(this)->implementation();
// ...
}
static void static_func()
{
// ...
Derived::static_sub_func();
// ...
}
};
struct Derived : Base<Derived>
{
void implementation();
static void static_sub_func();
};
Bien que je ne sache pas combien cela vous achète réellement. La surcharge d'un appel de fonction virtuelle est (dépendante du compilateur, bien sûr):
Alors que la surcharge du polymorphisme statique CRTP est: