2010-09-26 9 views
16

Je suis un nouveau programmeur en C++. et j'utilise des modèles pour la première fois.héritage de modèle C++

J'ai une classe abstraite et une autre classe l'étendant. mais tous les membres protégés de la classe abstraite ne sont pas reconnus par l'autre classe:

class0.h:

template<class T> 
class class0 { 

protected: 
    char p; 
public: 
    char getChar(); 
}; 

**class1.h** 
template<class T> 
class class1:public class0<T> { 
public: 
    void printChar(); 
}; 
template<class T> 
void class1<T>::printChar(){ 
    cout<< p<<endl;//p was not declared in this scope 
} 

merci. avoir une bonne semaine =)

+0

Vos classes de base ont besoin d'un destructeur virtuel public ou d'un destructeur non virtuel protégé/privé. – GManNickG

+0

BTW, quelle classe est abstraite dans ce domaine? – Chubsdad

Répondre

26

La raison pour laquelle cela se produit est de faire avec les règles de recherche pour les modèles.

p n'est pas une expression dépendante car il s'agit simplement d'un identifiant et non d'un élément dépendant du paramètre de modèle. Cela signifie que les classes de base dépendant du paramètre de modèle ne seront pas recherchées pour résoudre le nom p. Pour contourner ce problème, vous devez utiliser quelque chose qui dépend du paramètre de modèle. L'utilisation de this-> fera cela.

par exemple.

cout << this->p << endl; 
+0

Merci! cela a aidé =) passez une bonne journée! – yonka

+3

@yonka: Vous devriez accepter sa réponse. – GManNickG

+0

@GMan: Je ne sais pas; litb a posté une réponse maintenant. :-) –

2

Je ne reçois pas cette erreur de compilation dans VC9. Cependant, il y a plusieurs problèmes avec le code: Premièrement, il n'a pas besoin d'être une classe modèle comme c'est actuellement écrit ... mais peut-être vous l'avez simplement simplifié pour cette question? Deuxièmement, la classe de base devrait avoir un destructeur virtuel.

#include <iostream> 

using namespace std; 

class class0 { 
public: 
    virtual ~class0(){} 

protected: 
    char p; 
public: 
    char getChar(); 
}; 

class class1 : public class0 { 
public: 
    void printChar(); 
}; 

void class1::printChar(){ 
    cout << p << endl;//p was not declared in this scope 
} 

int main() { 
    class1 c; 
    c.printChar(); 
    return 1; 
} 

Depuis que vous apprenez sur les modèles, je suggère de ne pas mélanger les concepts (héritage & modèles) tout en apprenant. Commençons par un exemple simple comme ça ...

#include <iostream> 
#include <string> 

using namespace std; 

template <typename T> 
T add(const T& a, const T& b) { 
    return a + b; 
} 

int main() { 
    int x = 5; 
    int y = 5; 

    int z = add(x, y); 
    cout << z << endl; 

    string s1("Hello, "); 
    string s2("World!"); 

    string s3 = add(s1, s2); 
    cout << s3 << endl; 

    return 1; 
} 

Le concept important dans le code ci-dessus est que nous avons écrit fonction ONE qui sait comment ajouter des entiers et des chaînes (et beaucoup d'autres types d'ailleurs).

+4

Pourquoi la classe de base devrait avoir un destructeur virtuel? Les modèles sont souvent utilisés pour implémenter le polymorphisme paramétrique, et la suppression virtuelle n'est utile que pour le polymorphisme dynamique (et seulement si la suppression est effectuée de manière polymorphe). –

+1

Le compilateur Visual Studio 2008 est connu pour ne pas implémenter correctement les règles de recherche de modèle dans ce cas. C'est pourquoi vous ne voyez pas l'erreur. –

+0

@Ben Voigt, bon point mais l'OP commence juste avec des templates et je devine qu'ils n'ont probablement pas encore couvert ça. Mais il semble qu'ils aient couvert l'héritage et à moins qu'il ne soit spécifiquement en train de polymorphiser à la compilation, il est plus sûr de rendre le destructeur de base virtuel. – dgnorton

14

Pour un nom recherché dans une classe de base dépendante, deux conditions doivent être remplies

  • Il est nécessaire que la recherche n'est pas non qualifiée
  • Il est nécessaire que le nom est dépendante

Ces règles comme indiqué dans 03 C++ sont différents du rules stated by unrevised C++98, où satisfaire la deuxième puce (faire un nom dépendante) était suffisante pour trouver des noms déclarés dans les classes de base dépendantes.

Un nom dépendant est recherché au moment de l'instanciation et une recherche autre qu'une recherche non qualifiée n'ignore pas les classes de base dépendantes. Ces deux conditions doivent être satisfaites pour trouver un nom déclaré dans une classe de base dépendante, ni l'un ni l'autre n'est suffisant.Pour satisfaire à la fois les conditions que vous pouvez utiliser différentes constructions

this->p 
class1::p 

Les deux noms p sont dépendants et la première version utilise classe membre accès recherche et la deuxième version utilise nom qualifié recherche.