[转] c++的模板继承

华宰 发布于 2010/12/14 05:23
阅读 3K+
收藏 2

作者:清林,博客名:飞空静渡

我们有这么一组这样的类,其类继承关系如下图:

我们先把base, man, 和woman的类写出来,test.h文件

  1. #ifndef TEST_H  
  2. #define TEST_H   
  3. #include <iostream>  
  4. using namespace std;  
  5. class base   
  6. {  
  7. public:  
  8.     base (int id, bool bman):id_(id), bMan(bman){cout<<"base function!"<<endl;}  
  9.     virtual ~base (){}  
  10.     bool sexMan() { return bMan;}  
  11. protected:  
  12.     int id_;  
  13.     bool bMan; // false is woman, true :is man  
  14. };  
  15. class man :public base  
  16. {  
  17. public:  
  18.     man (int id):base(id, true){cout<<"I'am a man, id is "<<id_<<endl;}  
  19. protected:  
  20. };  
  21. class woman : public base  
  22. {  
  23. public:  
  24.     woman (int id): base(id, false){cout<<"I'am a woman, id is "<<id_<<endl;}  
  25. protected:  
  26.       
  27.       
  28. };  
  29. #endif  

#ifndef TEST_H #define TEST_H #include <iostream> using namespace std; class base { public: base (int id, bool bman):id_(id), bMan(bman){cout<<"base function!"<<endl;} virtual ~base (){} bool sexMan() { return bMan;} protected: int id_; bool bMan; // false is woman, true :is man }; class man :public base { public: man (int id):base(id, true){cout<<"I'am a man, id is "<<id_<<endl;} protected: }; class woman : public base { public: woman (int id): base(id, false){cout<<"I'am a woman, id is "<<id_<<endl;} protected: }; #endif

如果我们要写一个男教师的类manTeacher的话就得从man上继承,同理womanTeacher就得从woman上继承,这样我们就得写下两个类了,但这里我们可以通过模板来简化类的写,如下(在test.h文件下面添加):

  1. template<class T>   
  2. class teacher : public T   
  3. {  
  4. public:  
  5.     teacher(int id):T(id){}  
  6.     void say()  
  7.     {  
  8.         if (sexMan())  
  9.             cout<<"I'am a man teacher!"<<endl;  
  10.         else  
  11.             cout<<"I'am a woman teacher!"<<endl;  
  12.     }  
  13. private:  
  14.     /* data */  
  15. };  

template<class T> class teacher : public T { public: teacher(int id):T(id){} void say() { if (sexMan()) cout<<"I'am a man teacher!"<<endl; else cout<<"I'am a woman teacher!"<<endl; } private: /* data */ };

我们测试一下,新建一个cpp文件,main.cpp

  1. #include <vector>  
  2. #include "test.h"  
  3. int main(int argc, char *argv[])  
  4. {  
  5.     teacher<man> t1(5);  
  6.     t1.say();  
  7.       
  8. }  

#include <vector> #include "test.h" int main(int argc, char *argv[]) { teacher<man> t1(5); t1.say(); }

在vc上可以直接编译,在g++上,要添加-fpermissive,添加这个可以让模板代码由出错降为警告,从而编译通过,vc可以直接编译通过。

编译:

g++ -g -Wall -fpermissive main.cpp

运行: ./a.out
base function!
I'am a man, id is 5
I'am a man teacher!

我们再次修改如下:

  1. #include <vector>  
  2. #include "test.h"  
  3. int main(int argc, char *argv[])  
  4. {  
  5.     base* b = new teacher<man>(3);  
  6.     teacher<man> *t = (teacher<man> *)b;  
  7.     t->say();  
  8.     return 0;  
  9. }  

#include <vector> #include "test.h" int main(int argc, char *argv[]) { base* b = new teacher<man>(3); teacher<man> *t = (teacher<man> *)b; t->say(); return 0; }

编译输出:./a.out
base function!
I'am a man, id is 3
I'am a man teacher

再次修改main.cpp

  1. #include <vector>  
  2. #include "test.h"  
  3. int main(int argc, char *argv[])  
  4. {  
  5.     std::vector<base*> vb;  
  6.     base* b1 = new teacher<man>(3);  
  7.     base* b2 = new teacher<woman>(5);  
  8.     vb.push_back(b1);  
  9.     vb.push_back(b2);  
  10.     for(std::vector<base*>::iterator it = vb.begin();  
  11.             it != vb.end();  
  12.             ++it)  
  13.     {  
  14.         if ((*it)->sexMan())  
  15.         {  
  16.             teacher<man> *t = (teacher<man> *) (*it);  
  17.             t->say();  
  18.         }  
  19.         else  
  20.         {  
  21.             teacher<woman> *t = (teacher<woman> *) (*it);  
  22.             t->say();  
  23.         }  
  24.     }  
  25.     return 0;  
  26. }  

#include <vector> #include "test.h" int main(int argc, char *argv[]) { std::vector<base*> vb; base* b1 = new teacher<man>(3); base* b2 = new teacher<woman>(5); vb.push_back(b1); vb.push_back(b2); for(std::vector<base*>::iterator it = vb.begin(); it != vb.end(); ++it) { if ((*it)->sexMan()) { teacher<man> *t = (teacher<man> *) (*it); t->say(); } else { teacher<woman> *t = (teacher<woman> *) (*it); t->say(); } } return 0; } 编译输出:./a.out
base function!
I'am a man, id is 3
base function!
I'am a woman, id is 5
I'am a man teacher!
I'am a woman teacher!

加载中
0
xyz555
xyz555

这个例子不好,没有显示出模板继承的优点。

既然true,false分别代表不同性别,初始化时使用不同参数值就可以了,甚至连模板都没必要用。

class base     
{    
public:    
    base (int id, bool bman):id_(id), bMan(bman){cout<<"base function!"<<endl;}    
    virtual ~base (){}    
    bool sexMan() { return bMan;}    
    void say()    
    {    
        if (sexMan())    
            cout<<"I'am a man teacher!"<<endl;    
        else    
            cout<<"I'am a woman teacher!"<<endl;    
    }    
protected:    
    int id_;    
    bool bMan; // false is woman, true :is man    
};   
base man(123, true);

base woman(456, false);
0
xyz555
xyz555

使用继承的话可以这样。

class base         
{        
public:        
    base (int id, bool bman):id_(id), bMan(bman){cout<<"base function!"<<endl;}        
    virtual ~base (){}        
    bool sexMan() { return bMan;}   
protected:        
    int id_;        
    bool bMan; // false is woman, true :is man        
};  
  
class teacher : public base  
{  
public:  
    teacher(int id, bool bman):base(id, bman){}  
    void say()        
    {        
        if (sexMan())        
            cout<<"I'am a man teacher!"<<endl;        
        else        
            cout<<"I'am a woman teacher!"<<endl;        
    }        
}  
   
teacher man(123, true);    
    
teacher woman(456, false);  
这里使用了2个类,而模板继承却使用了3个类。

这样的模板继承只要类设计的好的话好像没什么太大意义。

另外类中的成员属性是一个类的情况也可以替代这种情况。

0
xyz555
xyz555

作为一种技术讨论还是不错。但实际应用的话可能会很有问题,最大的问题是,子类使用模板继承后很容易引起混乱,到底子类是继承至那个类?

class man 
{
public:
   base manTeacher(id, true);
public:  
    man (){}  
protected:  
};  
class woman
{
public:
   base manTeacher(id, false);
public:  
    woman (){};
protected:     
};  

我想这样的方式应该优于楼主的模板继承。

使用模板的话也可以这样。

template <class T>
class teacher
{
public:
    T sTeacher;
public:    
    teacher(){}      
} 

这也就是我上面说的“ 类中的成员属性是一个类的情况”。这样应该可以完全替代楼主的模板继承。

0
ffl
ffl

这个东西怎么用才合理 至今不解

返回顶部
顶部