2010-05-20 8 views
3

Je rencontre des problèmes d'héritage multiple provenant d'instanciations différentes de la même classe de modèles. Plus précisément, je suis en train de le faire:Héritage multiple à partir de la classe de modèles

template <class T> 
class Base 
{ 

public: 

    Base() : obj(NULL) 
    { 
    } 

    virtual ~Base() 
    { 
     if(obj != NULL) delete obj; 
    } 

    template <class T> 
    T* createBase() 
    { 
     obj = new T(); 

     return obj; 
    } 

protected: 

    T* obj; 

}; 

class Something 
{ 
    // ... 
}; 

class SomethingElse 
{ 
    // ... 
}; 

class Derived : public Base<Something>, public Base<SomethingElse> 
{ 

}; 

int main() 
{ 
    Derived* d = new Derived(); 
    Something* smth1 = d->createBase<Something>(); 
    SomethingElse* smth2 = d->createBase<SomethingElse>(); 

    delete d; 

    return 0; 
} 

Lorsque je tente de compiler le code ci-dessus, je reçois les erreurs suivantes:

1>[...](41) : error C2440: '=' : cannot convert from 'SomethingElse *' to 'Something *' 
1>  Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast 
1>  [...](71) : see reference to function template instantiation 'T *Base<Something>::createBase<SomethingElse>(void)' being compiled 
1>  with 
1>  [ 
1>   T=SomethingElse 
1>  ] 
1>[...](43) : error C2440: 'return' : cannot convert from 'Something *' to 'SomethingElse *' 
1>  Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast 

La question semble être l'ambiguïté en raison de l'être membre hérité à la fois la base < Quelque chose> et base de < SomethingElse>, et je peux travailler autour d'elle par disambiguating mes appels à createBase:

Something* smth1 = d->Base<Something>::createBase<Something>(); 
SomethingElse* smth2 = d->Base<SomethingElse>::createBase<SomethingElse>(); 

Cependant, t sa solution est terriblement impraticable, syntaxiquement parlant, et je préférerais quelque chose de plus élégant. De plus, je suis intrigué par le premier message d'erreur. Cela semble impliquer qu'il existe une instanciation createBase < SomethingElse> dans Base < Quelque chose>, mais comment est-ce possible? Toute information ou conseil concernant ce problème serait grandement apprécié.

+0

Est-ce que le comportement du compilateur est correct? Je dirais que cela devrait entraîner une ambiguïté et une erreur de compilation. – jpalecek

+0

J'ai eu des sentiments étranges à propos de l'utilisation de modèles mélangés avec l'héritage. Quoi qu'il en soit, si vous voulez éviter la syntaxe à long terme, utilisez 'typedef'. –

Répondre

2

Il semble entendre qu'il existe une instanciation createBase<SomethingElse> dans Base<Something>, mais comment est-ce possible?

Il y a sûrement, parce que votre createBase<T>() est une fonction de modèle de membre (et la T dans cette fonction n'a rien à voir avec le T dans la classe environnante).

je ferais quelque chose comme:

// in Derived, or you could make some class (eg. MultiBase) for it 

template <class T> 
T* createBase() 
{ 
    return Base<T>::createBase(); 
} 
0

Les « noms complets » des deux fonctions est quelque chose comme ceci:

template<class T> T* Derived::Base<Something>::createBase<T>(); 

D'après ce que je sais, votre fonction createBase() est une fonction templated dans une classe modélisée. D'après ce que je peux voir, vous voulez laisser tomber le `template`` devant.

Toutefois, cela ne devrait pas résoudre complètement votre problème, car Derived serait alors (encore) ont tous deux Base<Something>::createBase() et Base<SomethingElse>::createBase(). La réponse de

jpalecek terminerait résoudre le problème pour vous, ou vous pouvez accéder à l'objet comme si elle était une base particulière:

Base<Something> * pBase = new Derived(); 
pBase->createBase(); 

ou

static_cast<Base<Something> >(d)->createBase(); 

Ou, pour ajouter à la réponse de jpalecek ,

static_cast<Base<T> >(this)->createBase(); 

Devrait fonctionner, et je pense être de type sécurisé; c'est-à-dire, ne fonctionnera pas si this n'hérite pas de Base<T>

Questions connexes