2010-02-03 3 views

Répondre

7

J'ai déjà rencontré ce problème auparavant. Bien qu'il existe des moyens de résoudre votre problème, vous devriez abandonner l'idée d'une classe de base vectorielle. Ce que vous devriez probablement faire à la place, c'est imiter la façon dont le conteneur STL C++ est conçu.

La liste STL est constituée de concepts plutôt que de classes de base. Un std::vector est un modèle du concept Container, mais n'hérite pas d'une classe de base Container. Un concept est un ensemble d'exigences auxquelles tout modèle du concept doit adhérer. Voir page this pour les exigences pour Container par exemple.

Les exigences pour Container Etat, par exemple que vous typedef le type de contenu du récipient comme value_type et typedef itérateurs comme iterator et const_iterator. En outre, vous devez définir les fonctions begin() et end() renvoyant des itérateurs, et ainsi de suite.

Vous devrez ensuite modifier les fonctions qui fonctionnent sur votre classe de base Vector pour opérer à la place sur toute classe qui respecte les exigences imposées par le concept. Cela peut être fait en rendant les fonctions modélisées. Vous ne devez pas nécessairement vous en tenir aux concepts utilisés par la STL, vous pouvez aussi bien préparer les vôtres. S'en tenir aux concepts tels qu'ils sont définis dans la STL a l'avantage supplémentaire que les algorithmes STL (std::sort par exemple) peuvent fonctionner sur vos conteneurs.

Exemple rapide:

class VectorImplA 
{ 
public: 
    typedef VectorImplAIterator iterator; 

    iterator begin(); 
    iterator end(); 
}; 

class VectorImplB 
{ 
public: 
    typedef VectorImplBIterator iterator; 

    iterator begin(); 
    iterator end(); 
}; 

template <typename VectorConcept> 
void doSomeOperations(VectorConcept &container) 
{ 
    VectorConcept::iterator it; 
    it = container.begin(); 
} 

int main() 
{ 
    VectorImplA vecA; 
    VectorImplB vecB; 
    doSomeOperations(vecA); // Compiles! 
    doSomeOperations(vecB); // Compiles as well! 
} 

En prime, pour répondre à la question initiale, pensez à la conception suivante (je ne voudrais pas aller de cette façon si!):

struct IteratorBase 
{ 
    virtual void next() = 0; 
}; 

struct IteratorA : IteratorBase 
{ 
    void next() {}; 
}; 

struct IteratorB : IteratorBase 
{ 
    void next() {}; 
}; 

class Iterator 
{ 
    IteratorBase *d_base; 
public: 
    void next() { d_base->next(); } 
}; 
+0

+1 bien que je n'utiliserais certainement PAS une opération 'next', mieux vaut respecter les conventions habituelles pour l'interopérabilité avec STL. –

+0

Merci pour les réponses. J'ai déjà implémenté # 1, qui a été décrit ci-dessus. Le problème avec cela est que je ne peux pas avoir de polymorphisme d'exécution. c'est-à-dire, dériver VectorImplA et VectorImplB à partir du vecteur de classe de base et utiliser Vector * pour opérer sur les classes dérivées. Ai-je raison ? – Surya

0

Une possibilité consiste à utiliser une classe de modèle pour votre conteneur, avec le conteneur de données privé en tant que paramètre. De cette façon, l'itérateur peut être défini dans la classe indépendamment du conteneur de données.
Je ne suis pas sûr si c'est assez "unifié" pour ce dont vous avez besoin.

0

je faisais face à la même problème avant. Je solution # 2 avec une légère modification dans la définition de la classe Iterator

class Iterator :public boost::iterator_facade<Iterator,element_type, forward_traversal_tag> 
{ 
    ... 
} 

De cette façon, j'ai pu utiliser des algorithmes de STL avec mes conteneurs.

Questions connexes