8
votes

Classe de base générique avec des classes dérivées spécialisées de plusieurs gabarits

J'ai une quantité finie de classes avec la même implémentation, le seul différent étant le type de données sous-jacent qu'ils manipulent: xxx pré>

J'aimerais réduire la duplication de code de Ces classes en utilisant des modèles comme: p> xxx pré>

et spécialisation: p> xxx pré>

Cela fonctionne bien. mais strong> J'aimerais également ajouter une classe de base abstrait à ces classes spécialisées pour pouvoir les manipuler de manière générique (par exemple, dans une collection). Le problème est que cette classe de base doit avoir le getdata ​​code> et setdata ​​code> pour pouvoir les appeler même sans connaître le type dynamique de l'objet manipulé. P>

Je voudrais le mettre en œuvre avec quelque chose comme ceci: p> xxx pré>

et l'utiliser comme ça: p>

int main(int argc, char const *argv[])
{
    IntContainer intc = IntContainer();
    intc.setData(42);
    std::cout << intc.getData() << std::endl;

    BoolContainer boolc = BoolContainer();
    boolc.setData(false);
    std::cout << boolc.getData() << std::endl;

    std::vector<Base> v;
    v.push_back(intf);
    v.push_back(boolf);

    for (std::vector<Base>::iterator it = v.begin() ; it != v.end(); ++it)
        std::cout << it->getData() << std::endl;

    return 0;
}


4 commentaires

Qu'espérez-vous pouvoir faire en ajoutant cette classe de base? La connaissance de cela façonnerait fortement des réponses potentielles.


Fondamentalement, j'espérais avoir un ensemble de méthodes de cours dérivées fortement typées (c.-à-d. Ne pouvoir appeler setingdata (int Data) sur un boolcontainer ) mais avec la capacité Itérer sur une collection de ces classes (probablement un std :: vecteur ).


... Mais peut-être que je pense trop avec un objectif objectif de ces jours-ci.


Je pense que le mauvais tour était de choisir le polymorphisme de la compilée (modèles) lorsque vous souhaitez retarder ce comportement jusqu'au temps d'exécution (collections arbitraires de ces objets)


4 Réponses :


5
votes

Il n'y a tout simplement aucun moyen de faire ce que vous voulez.

Le problème est que, si cela a été autorisé, le compilateur devrait générer autant de méthodes virtuelles dans la classe de base, car il existe des spécialisations possibles de la classe enfant de modèle (c'est-à-dire une infini) qui n'est pas possible.


2 commentaires

D'accord - Ce que vous voulez, c'est une langue dactylographiée dynamiquement, que c ++ n'est pas.


Sachant que je n'ai besoin que d'une quantité finie de classes dérivées (je ne veux pas de «généricité complète», seulement du code sec), connaissez-vous un moyen de contourner mon problème?



3
votes

Du faire de la fabrication de modèle de base aussi? Bien sûr, il n'y a aucun moyen de faire quelque chose comme xxx pré>

mais le reste que vous pouvez réaliser avec quelque chose de simple comme p> xxx pré>

vous pouvez utiliser de quelque manière que ce soit aussi longtemps que les types correspondent. P>

IntContainer intc = IntContainer();
intc.setData(42);
std::cout << intc.getData() << std::endl;

BoolContainer boolc = BoolContainer();
boolc.setData(true);
std::cout << boolc.getData() << std::endl;

std::vector<IntContainer> v;
v.push_back(intc);
// v.push_back(boolc); No can't do.


0 commentaires

1
votes

Il s'agit d'une solution pour tout type de classes pouvant aller-t'aller via un stringstream , et une telle conversion est la bonne façon de convertir entre les types. Ce n'est pas efficace du tout: xxx

avec moins de types, vous pouvez faire quelque chose de similaire, tant que vous avez des fonctions de conversion entre eux.

Alternativement, si vous comme des exceptions, vous pouvez lancer.

Alternativement, vous pouvez utiliser boost :: variante S, qui ne font aucune conversion, mais fonctionne à partir d'une liste finie de types (ils sont fondamentalement étiquetés. Union S qui prend en charge plus de types que c ++ 03 laisse Union et avec une belle sémantique sur Attribuer / copier / etc.).


0 commentaires

1
votes

En supposant que vous avez une certaine flexibilité de conception, vous pouvez modifier votre interface pour accueillir cela, bien que ce n'est pas aussi efficace qu'une table virtuelle infinie

Vous pouvez définir des valeurs via la construction, ou >> < / p>

Vous pouvez obtenir des valeurs via <<< / code>

Votre vecteur doit être un pointeur de base ou une référence, la taille de chaque base L'objet est variable, le pointeur, explicite ou implicite à travers une référence est d'une taille fixe

Notez que les copies sont plus efficaces si le compilateur sait qu'il copie d'un générique à un autre par opposition à la base à la base xxx


0 commentaires