2009-11-14 5 views
1

Je suis nouveau à la programmation de classe générique alors peut-être ma question est stupide - désolé. Je voudrais savoir si la chose suivante est possible et - si oui, comment le faireC++ classes génériques et l'héritage

J'ai un simple fournisseur de classe générique, qui fournit des valeurs de type générique:

template <class A_Type> class Provider{ 
public: 
A_Type getValue(); 
    void setSubProvider(ISubProvider* subProvider) 
private: 
A_Type m_value; 
ISubProvider* m_subProvider; 
}; 

Le getValue La fonction retournera m_value dans le cas où m_subProvider est NULL. Mais si SubProvider n'est pas Null, la valeur doit être calculée par la classe SubProvider.

donc subprovider doit être de type générique aussi, mais je créer comme une classe abstraite sans mise en œuvre:

template <class A_Type> class ISubProvider{ 
public: 
virtual A_Type getValue() = 0; 
}; 

maintenant je veux que les implémentations actuelles de ISubProvider être non générique! par exemple, je veux mettre en œuvre IntegerProvider qui retourne le type entier

class IntegerProvider : public ISubProvider{ 
    int getValue(){return 123;} 
}; 

et peut-être un StringProvider:

class StringProvider : public ISubProvider{ 
    string getValue(){return "asdf";} 
}; 

maintenant - comment puis-je coder la chose, de sorte que je peux utiliser le

void setSubProvider(ISubProvider* subProvider) 

fonction du fournisseur de classe uniquement avec un subprovider qui correspond au type générique de fournisseur?

par exemple, si j'instancier un fournisseur de type int:

Provider<int> myProvider = new Provider<int>(); 

alors il doit être possible d'appeler

myProvider.setSubProvider(new IntegerProvider()); 

mais il doit être impossible d'appeler

myProvider.setSubProvider(new StringProvider()); 

J'espère que vous comprenez ma question et peut me dire comment créer ce code correctement :)

Merci!

Répondre

3

C++ a des modèles (modèles de classe et des modèles de fonction), pas de génériques.

Etant donné cette déclaration:

template <class A_Type> class ISubProvider; 

vous ne pouvez pas le faire:

class IntegerProvider : public ISubProvider{ 
    int getValue(){return 123;} 
}; 

parce ISubProvider est pas une classe, il est un modèle de classe.

Vous pouvez cependant, faites ceci.

class IntegerProvider : public ISubProvider<int> { 
    int getValue(){return 123;} 
}; 

Je pense que c'est ce que vous voulez faire, dans tous les cas.

Cela ne fonctionnera pas non plus pour la même raison.

template <class A_Type> class Provider { 
public: 
    A_Type getValue(); 
    void setSubProvider(ISubProvider* subProvider) 
private: 
    A_Type m_value; 
    ISubProvider* m_subProvider; 
}; 

Vous devez faire quelque chose comme ça.

template <class A_Type> class Provider { 
public: 
    A_Type getValue(); 
    void setSubProvider(ISubProvider<A_Type>* subProvider); 
private: 
    A_Type m_value; 
    ISubProvider<A_Type>* m_subProvider; 
}; 

Vous avez maintenant réaliser ce que vous vouliez dans que vous devez fournir un pointeur sur un ISubProvider instantiation pour le même paramètre de type de modèle comme modèle de classe Provider.

Notez, cependant, que vous avez vraiment rien gagné en utilisant une classe de base du type basé sur un modèle dans ce cas.

1

Vous devez tirer de votre ISubProvider de la manière suivante

class IntegerProvider : public ISubProvider<int> 
class StringProvider : public ISubProvider<string> 

Et ainsi de suite

changer aussi vous déclaration de classe

template <class A_Type> class Provider{ 
public: 
A_Type getValue(); 
    void setSubProvider(ISubProvider<A_Type>* subProvider) 
private: 
A_Type m_value; 
ISubProvider<A_Type>* m_subProvider; 
}; 
0

Si vous laissez tomber l'idée séparée d'un fournisseur/sous-fournisseur et juste créer un seul fournisseur, votre problème se résout.

template <class A_Type> class Provider{ 
    typedef Provider<A_Type> my_type; 

public: 
    A_Type getValue(); 
    void setSubProvider(my_type* subProvider) 
private: 
    A_Type m_value; 
    my_type* m_subProvider; 
}; 
Questions connexes