c++类模板是怎么理解
定义类模板的一般形式是:template<类型名参数名1,类型名参数名2,…>class类名{类声明体};例如,template<classT>classSmemory{...
定义类模板的一般形式是:
template <类型名 参数名1,类型名 参数名2,…>
class 类名
{
类声明体
};
例如,template <class T>
class Smemory
{…
public:
void mput(T x);
…
}
表示定义一个名为Smemory的类模板,其中带类型参数T。
在类模板的外部定义类成员函数的一般形式是:
template <类型名 参数名1,类型名 参数名2,…>
函数返回值类型 类名<参数名 1 参数名 2,…>::成员函数名(形参表)
{
函数体
}
这里的template<class T> 这个参数是做什么用的 什么意思 展开
template <类型名 参数名1,类型名 参数名2,…>
class 类名
{
类声明体
};
例如,template <class T>
class Smemory
{…
public:
void mput(T x);
…
}
表示定义一个名为Smemory的类模板,其中带类型参数T。
在类模板的外部定义类成员函数的一般形式是:
template <类型名 参数名1,类型名 参数名2,…>
函数返回值类型 类名<参数名 1 参数名 2,…>::成员函数名(形参表)
{
函数体
}
这里的template<class T> 这个参数是做什么用的 什么意思 展开
5个回答
展开全部
模板类英文为class template,template的中文翻译为模板,所以模板类的意思其实是:类的模板。
顾名思义,模板类是相当于一个模具,当参数给定时,生成具体的类,也叫实例化。它的提出主要是为了减少代码重复。
例如,我们可以用下面的代码交换两个数b和c
a = b;
b = c;
c = a;
这个交换过程与a,b,c的具体类型没有关系,因此我们可以用它来交换两个整数,或者两个浮点数。更一般的,我们可以用来交换两个具有赋值运算符的类型。因此,可以用模板进行一般化:
template<class T>
void swap(T &b, T &c){
a = b;
b = c;
c = a;
}
当然,上面介绍的这个不是模板类,而是模板函数。不过他们的概念是类似的。其中一开始的template代表后面尖括号中的是模板参数(类似于函数的参数),class代表参数是类(相应的,可以用template<int N>来声明整型参数)。后面的代码和的函数基本没有区别,只是用T来代替了具体的类型,例如int,double等。根据需要我们可以用swap<int>(b,c)来交换两个整数,swap<double>(b,c)交换两个浮点数。由于编译器可以根据b,c的具体类型推导T的具体含义,因此可以简写为swap(b,c)。
回到模板类,假设我们需要一个类型来代表动态数组,且该类型支持size成员函数。如果是整型的类,我们可能会写
class vector_int{
size_t size() const;
};
如果某一天,我们又需要浮点类型的动态数组,可能又会写
class vector_double{
size_t size() const;
};
于是就会发现它们的代码是如此的类似,因此我们希望将它一般化。如同swap函数的做法,我们将它定义为模板类:
template<class T>
class vector{
size_t size() const;
};
因此,vec_int等同于vector<int>,而vector_double等同于vector<double>。因为运用模板类的语法类似于
vector<T> a;
因此,编译器没办法为我们推导T的具体含义,所以不能像模板函数一样进行简写。
当然,上面是比较简单的情况,有时候我们需要的类在大多数情况下是一样的,但是对于某几个特殊情形可能不太一样,例如我们可能希望对于bool类型的数组能尽量减少内存的使用,用一个比特位代表一个bool值。从而,我们的数组不是通过bool a[10]的形式来定义。在这种情况下,c++提供了模板特化,也就是说当模板的参数取某个具体的值时,我们使用不同的模板,定义方式如下:
template<>
class vector<bool>{
size_t size() const;
};
顾名思义,模板类是相当于一个模具,当参数给定时,生成具体的类,也叫实例化。它的提出主要是为了减少代码重复。
例如,我们可以用下面的代码交换两个数b和c
a = b;
b = c;
c = a;
这个交换过程与a,b,c的具体类型没有关系,因此我们可以用它来交换两个整数,或者两个浮点数。更一般的,我们可以用来交换两个具有赋值运算符的类型。因此,可以用模板进行一般化:
template<class T>
void swap(T &b, T &c){
a = b;
b = c;
c = a;
}
当然,上面介绍的这个不是模板类,而是模板函数。不过他们的概念是类似的。其中一开始的template代表后面尖括号中的是模板参数(类似于函数的参数),class代表参数是类(相应的,可以用template<int N>来声明整型参数)。后面的代码和的函数基本没有区别,只是用T来代替了具体的类型,例如int,double等。根据需要我们可以用swap<int>(b,c)来交换两个整数,swap<double>(b,c)交换两个浮点数。由于编译器可以根据b,c的具体类型推导T的具体含义,因此可以简写为swap(b,c)。
回到模板类,假设我们需要一个类型来代表动态数组,且该类型支持size成员函数。如果是整型的类,我们可能会写
class vector_int{
size_t size() const;
};
如果某一天,我们又需要浮点类型的动态数组,可能又会写
class vector_double{
size_t size() const;
};
于是就会发现它们的代码是如此的类似,因此我们希望将它一般化。如同swap函数的做法,我们将它定义为模板类:
template<class T>
class vector{
size_t size() const;
};
因此,vec_int等同于vector<int>,而vector_double等同于vector<double>。因为运用模板类的语法类似于
vector<T> a;
因此,编译器没办法为我们推导T的具体含义,所以不能像模板函数一样进行简写。
当然,上面是比较简单的情况,有时候我们需要的类在大多数情况下是一样的,但是对于某几个特殊情形可能不太一样,例如我们可能希望对于bool类型的数组能尽量减少内存的使用,用一个比特位代表一个bool值。从而,我们的数组不是通过bool a[10]的形式来定义。在这种情况下,c++提供了模板特化,也就是说当模板的参数取某个具体的值时,我们使用不同的模板,定义方式如下:
template<>
class vector<bool>{
size_t size() const;
};
展开全部
你不要跟着他绕,越绕越头晕,你只要记住这里的T代表一种类型就行了。模版实例化时只是把T用相应的类型替换。
如简单的min模版:
template<class T>
T min(T a, T b){return a<b?a:b;}
实例化:
int x = 100;
int y = 200;
int z = min(x,y); //这里的x、y都为int型,就相当于实例化了一个int型的min模版,你把int代上面T就清楚了
类模版也是一样的
template<class T>//也可用template<typename T>,并且这是最新的C++标准
class C2DPoint //2D点坐标模版
{
public:
C2DPoint(T x=0, T y=0):m_x(x), m_y(y){}
void X(T x){m_x = x;}
void Y(T y){m_y = y;}
T X(void)const{return m_x;}
T Y(void)const{return m_y;}
void Print()const;
private:
T m_x, m_y;
};
template<typename T>
void C2DPoint<T>::Print()const
{
std::cout<<"x:"<<m_x<<" y:"<<m_y<<std::endl;
}
int main()
{
C2DPoint<int> p0; //这里相当于把int代回模版中T的位置
p0.X(10);
p0.Y(20);
p0.Print();
C2DPoint<float> p1(100, 200.5);//这里相当于把float代回模版中T的位置
p1.Print();
return 0;
}
如简单的min模版:
template<class T>
T min(T a, T b){return a<b?a:b;}
实例化:
int x = 100;
int y = 200;
int z = min(x,y); //这里的x、y都为int型,就相当于实例化了一个int型的min模版,你把int代上面T就清楚了
类模版也是一样的
template<class T>//也可用template<typename T>,并且这是最新的C++标准
class C2DPoint //2D点坐标模版
{
public:
C2DPoint(T x=0, T y=0):m_x(x), m_y(y){}
void X(T x){m_x = x;}
void Y(T y){m_y = y;}
T X(void)const{return m_x;}
T Y(void)const{return m_y;}
void Print()const;
private:
T m_x, m_y;
};
template<typename T>
void C2DPoint<T>::Print()const
{
std::cout<<"x:"<<m_x<<" y:"<<m_y<<std::endl;
}
int main()
{
C2DPoint<int> p0; //这里相当于把int代回模版中T的位置
p0.X(10);
p0.Y(20);
p0.Print();
C2DPoint<float> p1(100, 200.5);//这里相当于把float代回模版中T的位置
p1.Print();
return 0;
}
本回答被提问者采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
template<class T> 算不上参数。这句主要是说类Smemory使用了带参数 T 的类模板,是模板声明。
就是说Smemory类里使用了 T 类型的数据或对象。在具体使用时,要进行初始化。例如:要建立类 Smemory的对象。可以如下:
Smemory<int> obj;
Smemory<double> obj1;
还可以进行其他类型的初始化。
自己写的一个简单的图形类,可以参考一下:
#include <iostream>
using namespace std;
const double PI=3.1415926;
template<class T>
class Shape
{
protected:
T x,y;
public:
Shape(T tx,T ty){x=tx;y=ty;}
virtual T area()=0;
virtual T length()=0;
virtual void show()=0;
};
template <class T>
class Circle:public Shape<T>
{
protected:
T radius;
public:
Circle(T x,T y,T r):Shape<T>(x,y){radius=r;}
T area(){return PI*radius*radius;}
T length(){return 2*PI*radius;}
void show(){cout<<"Area="<<area()<<",Length="<<length()<<endl;}
};
template <class T>
class Rectangle:public Shape<T>
{
protected:
T h,w;
public:
Rectangle(T x,T y,T th,T tw):Shape<T>(x,y){h=th;w=tw;}
T area(){return h*w;}
T length(){return 2*(h+w);}
void show(){cout<<"Area="<<area()<<",Length="<<length()<<endl;}
};
void main()
{
Circle<double> Cobj(2,3,1);
Rectangle<double> Robj(2,3,3,4);
Cobj.show();
Robj.show();
void (Shape<double>::*pf)();
pf=Shape<double>::show;
(Cobj.*pf)();
(Robj.*pf)();
Shape<double> *p;
p=&Cobj;
p->show();
p=&Robj;
p->show();
system("pause");
}
就是说Smemory类里使用了 T 类型的数据或对象。在具体使用时,要进行初始化。例如:要建立类 Smemory的对象。可以如下:
Smemory<int> obj;
Smemory<double> obj1;
还可以进行其他类型的初始化。
自己写的一个简单的图形类,可以参考一下:
#include <iostream>
using namespace std;
const double PI=3.1415926;
template<class T>
class Shape
{
protected:
T x,y;
public:
Shape(T tx,T ty){x=tx;y=ty;}
virtual T area()=0;
virtual T length()=0;
virtual void show()=0;
};
template <class T>
class Circle:public Shape<T>
{
protected:
T radius;
public:
Circle(T x,T y,T r):Shape<T>(x,y){radius=r;}
T area(){return PI*radius*radius;}
T length(){return 2*PI*radius;}
void show(){cout<<"Area="<<area()<<",Length="<<length()<<endl;}
};
template <class T>
class Rectangle:public Shape<T>
{
protected:
T h,w;
public:
Rectangle(T x,T y,T th,T tw):Shape<T>(x,y){h=th;w=tw;}
T area(){return h*w;}
T length(){return 2*(h+w);}
void show(){cout<<"Area="<<area()<<",Length="<<length()<<endl;}
};
void main()
{
Circle<double> Cobj(2,3,1);
Rectangle<double> Robj(2,3,3,4);
Cobj.show();
Robj.show();
void (Shape<double>::*pf)();
pf=Shape<double>::show;
(Cobj.*pf)();
(Robj.*pf)();
Shape<double> *p;
p=&Cobj;
p->show();
p=&Robj;
p->show();
system("pause");
}
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
T 就是定义了一种类型 在后面使用的时候 会给他一个初始化的值
#include<iostream>
using namespace std;
const int StackSize=100;
template<class T>
class SeqStack
{
public:
SeqStack(){top=-1;}
~SeqStack(){}
void Push(T x);
T Pop();
T GetTop(){if(top!=-1)return data[top];}
bool Empty();
void Print();
private:
T data[StackSize];
int top;
};
template<class T>
bool SeqStack<T>::Empty()
{
if (top==-1)
return true;
else return false;
}
template<class T>
void SeqStack<T>::Push(T x)
{
if(top == StackSize-1)throw"上溢";
top++;
data[top]=x;
}
template<class T>
T SeqStack<T>::Pop()
{
if (top==-1)throw"下溢";
T x=data[top];
top--;
return x;
}
template<class T>
void SeqStack<T>::Print()
{
int i;
cout<<"the stack is:"<<endl;
cout<<"-------------"<<endl;
for(i=top;i>=0;i--)
{
cout<<" "<<data[i]<<endl;
cout<<"-------------"<<endl;
}
}
int main()
{
SeqStack<int>Stack;
int a,b,tab,f;
int flag=1;
f=0;
while(f==0)
{
cout<<"***************************"<<endl;
cout<<"*1.push *"<<endl;
cout<<"*2.pop *"<<endl;
cout<<"*3.if empty *"<<endl;
cout<<"*4.get top data *"<<endl;
cout<<"*5.exit *"<<endl;
cout<<"***************************"<<endl;
cin>>tab;
switch (tab)
{
case 1:
{
cout<<"please input a number:"<<endl;
cin>>a;
Stack.Push(a);
Stack.Print();
break;
}
case 2:
{
b=Stack.Pop();
cout<<"the number is:"<<b<<endl;
Stack.Print();
break;
}
case 3:
{
if(Stack.Empty())cout<<"true"<<endl;
else cout<<"flase"<<endl;
break;
}
case 4:
{
a=Stack.GetTop();
cout<<a<<endl;
break;
}
default:
{
f=1;
}
}
}
Stack.~SeqStack();
return 0;
}
#include<iostream>
using namespace std;
const int StackSize=100;
template<class T>
class SeqStack
{
public:
SeqStack(){top=-1;}
~SeqStack(){}
void Push(T x);
T Pop();
T GetTop(){if(top!=-1)return data[top];}
bool Empty();
void Print();
private:
T data[StackSize];
int top;
};
template<class T>
bool SeqStack<T>::Empty()
{
if (top==-1)
return true;
else return false;
}
template<class T>
void SeqStack<T>::Push(T x)
{
if(top == StackSize-1)throw"上溢";
top++;
data[top]=x;
}
template<class T>
T SeqStack<T>::Pop()
{
if (top==-1)throw"下溢";
T x=data[top];
top--;
return x;
}
template<class T>
void SeqStack<T>::Print()
{
int i;
cout<<"the stack is:"<<endl;
cout<<"-------------"<<endl;
for(i=top;i>=0;i--)
{
cout<<" "<<data[i]<<endl;
cout<<"-------------"<<endl;
}
}
int main()
{
SeqStack<int>Stack;
int a,b,tab,f;
int flag=1;
f=0;
while(f==0)
{
cout<<"***************************"<<endl;
cout<<"*1.push *"<<endl;
cout<<"*2.pop *"<<endl;
cout<<"*3.if empty *"<<endl;
cout<<"*4.get top data *"<<endl;
cout<<"*5.exit *"<<endl;
cout<<"***************************"<<endl;
cin>>tab;
switch (tab)
{
case 1:
{
cout<<"please input a number:"<<endl;
cin>>a;
Stack.Push(a);
Stack.Print();
break;
}
case 2:
{
b=Stack.Pop();
cout<<"the number is:"<<b<<endl;
Stack.Print();
break;
}
case 3:
{
if(Stack.Empty())cout<<"true"<<endl;
else cout<<"flase"<<endl;
break;
}
case 4:
{
a=Stack.GetTop();
cout<<a<<endl;
break;
}
default:
{
f=1;
}
}
}
Stack.~SeqStack();
return 0;
}
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
里面放一个类型,这个类里的所有T都成这个类型
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询
广告 您可能关注的内容 |