web-dev-qa-db-fra.com

Les méthodes virtuelles pures sont-elles autorisées dans une classe de modèle?

Une fois auparavant, j'étais certain que vous ne pouviez pas faire cela, mais l'autre jour, je jouais avec du code et il semblait compiler et fonctionner. Je veux juste vérifier que je n'ai pas seulement de la chance. Une classe de modèle peut-elle avoir une fonction virtuelle pure - ce qui, je suppose, signifierait également que des méthodes virtuelles simples seraient également valables pour le destructeur?

template <typename WordType> class DataSource
{
public:
    DataSource();
    DataSource(DataSource const& other);
    virtual ~DataSource();

    virtual void Put(
        WordType const* const data,
        unsigned int const wordCount) = 0;
}

J'ai essayé de le chercher en ligne et tout ce que j'ai pu trouver, c'est que vous ne pouvez pas avoir une méthode virtuelle (pure ou autre) dans une classe normale comme celle-ci:

class DataSource
{
public:
    DataSource();
    DataSource(DataSource const& other);
    virtual ~DataSource();

    template <typename WordType>
    virtual void Put(
        WordType const* const data,
        unsigned int const wordCount) = 0;
}

Et que cela est dû à l'impossibilité de gérer une table virtuelle pour référencer tous les différents types de types possibles avec lesquels cette méthode serait instanciée.

Cependant, lorsqu'il s'agit d'une fonction membre virtuelle d'une classe de modèle, cela semble différent parce que la classe entière elle-même est "créée" via le paramètre de modèle lorsque la variable de classe de modèle est instanciée. À ce stade, la méthode virtuelle est comme n'importe quelle autre méthode virale d'une classe en raison de la nature "trouver et remplacer" des modèles.

Quoi qu'il en soit, en posant à nouveau la question au cas où elle s'y perdrait: les fonctions virtuelles virtuelles (pures et/ou normales) sont-elles autorisées dans une classe tempate?

43
Anthony

Un modèle de classe peut en effet contenir des fonctions virtuelles ou virtuelles pures. Cela a été utilisé par Andrei Alexandresu dans "Modern C++ Design" pour implémenter le modèle de visiteur à l'aide de modèles et de listes de types. Vous pouvez voir le code ici dans sa bibliothèque Loki si vous êtes intéressé.

Avec la plupart des implémentations C++ standard, cela ne pose aucun problème, car lorsque le modèle est instancié, la fonction virtuelle finit par être une seule fonction. Par conséquent, le nombre de créneaux nécessaires dans la table virtuelle peut être connu au sein de l'unité de traduction, de sorte qu'une table virtuelle peut être générée.

Comme vous l'avez mentionné, vous ne pouvez pas avoir de fonction de membre de modèle virtuel car le nombre d'emplacements vtable ne serait pas connu dans l'unité de traduction.

J'espère que cela t'aides!

52
templatetypedef

Oui. Parfaitement légal.

.

8
jpalecek

Pensez à ce qu'est une classe de modèle - ce n'est pas une classe elle-même, mais un modèle que le compilateur peut utiliser pour créer des classes.

En tant que tel, il n'y a aucune raison pour laquelle vous ne pouvez pas inclure une fonction virtuelle (pure ou non) dans la définition de classe de modèle, car cela, en soi, ne génère aucun code, y compris la table virtuelle.

Lorsque nous instancions réellement la classe de modèle, par exemple DataSource<int>, alors le compilateur n'a besoin que de construire la table virtuelle pour ce type sélectionné, donc ce n'est pas différent d'une fonction virtuelle (pure ou autre) pour une classe non basée sur un modèle.

7
JohnMcG

Un modèle de classe avec des fonctions virtuelles est tout à fait correct. Mais, les fonctions de modèle avec un mot clé virtuel préfixé dans une classe ou une classe de modèle ne sont pas autorisées. Ci-dessous vous aiderait à obtenir cela:

//This is perfectly fine.
template <type T>
class myClass{
     virtual void function() = 0;
};

//This is NOT OK...
template<type T>
class myClass{
      template <type T>
      virtual void function() = 0;
};
3
Apte