c++的模板定义?
可能是我平常学得不是很好。又比较笨吧,对c++模板这块不是很熟悉,挺模糊的...希望高手给我指点哟,感激啊~~~T-T就是template<classType>之后,主函...
可能是我平常学得不是很好。又比较笨吧,对c++模板这块不是很熟悉,挺模糊的...希望高手给我指点哟,感激啊~~~ T-T
就是template<class Type>之后,主函数到底该如何定义?主要就是定义对象那一块.
希望大家随便举个例子赐教!!有点麻烦啊,再次谢谢了 展开
就是template<class Type>之后,主函数到底该如何定义?主要就是定义对象那一块.
希望大家随便举个例子赐教!!有点麻烦啊,再次谢谢了 展开
2013-07-25
展开全部
找本C++的书看看,上面讲的都比较详细,而且还有例子。
C++模板概述
只有使用C++语言的少数用户才努力尝试去理解模板的基本原理。然而那些希望去探索更多高级用法的人往往发现自己需要努力去理解模板是如何被语言所支持的,因为缺乏明确的说明。一个很大的问题在于一些工具只实现了C++标准的一个子集。本文将指出它们共同的缺陷并深入剖析如何使用C++模板快速产生可重用和高效的代码。
模板功能应用的典型是通过一系列模板类形成的完整类库,特别是STL和ATL。标准C++库(STL)提供了很多可重用和灵活的类及算法,而ATL则是使用C++进行COM编程的事实标准。要掌握这些及其它的模板库,理解模板是如何工作的这一基础是非常重要的。
函数模板
int main()
{
0 cout<<add(2,3)<<endl;
1 cout<<add(2.1,3)<<endl;
2 cout<<add(2,3.2)<<endl;
3 cout<<add(2.2,3.3)<<endl;
4 cout<<add("hello eone ","world")<<endl;
return 0;
}
也可以通过宏定义#define add(a,b) ((a)+(b))来实现,但是指针(字符串)不能直接相加.对于2,3,4需要进行模板特化.
通过重载函数,我们能够完成多种不同数据类型的相同操作。要实现两个double数值的加法和两个整数类型的加法,我们可以使用一个重载函数:
int add(const int x, const int y)
{
return x + y;
}
double add(const double x, const double y)
{
return x + y;
}
这时,编译器将根据它们的参数正确地解决这一问题。
// 调用int add(const int, const int);
const int z1 = add(3, 2);
// 调用double add(const double, const double);
const double z2 = add(3.0, 2.0);
如果我们需要处理其它类型,我们就不得不提供其他函数重载。对每个不同的数据类型实现一个函数重载,它们都遵循相同的模式,每当我们需要调用针对某一数据类型的函数时,原则上编译器为我们生成相应的代码。而一个模板函数则以如下方式实现:
template<class T>
const T add(const T &t1, const T &t2)
{
return t1 + t2;
}
从概念上来说,编译器通过模板关键字(后面跟随着模板由一或多个模板参数构成的参数列表)来识别模板。当为某一具体类型调用add时,编译器将根据模板定义并用给定的类型替换出现在模板中的参数。在这个例子中,模板参数列表由一个独立的类型模板参数T构成。使用一个模板函数替代函数重载,编译器可以自动为所需的新类型生成代码
我们可以对任何拥有+操作符定义的类型使用add模板。假设一个自定义的String类提供了字符串连接并知道如何将自身写入到std::ostream。因为String与该模板函数兼容,因此我们可以调用它来实现字符串相加:
// 示例字符串
const string strBook("book");
const string strWorm("worm");
// 显示 "bookworm".
cout << add(strBook, strWorm) << endl;
Seeing that we intended to add two String values, the compiler will generate the appropriate add function on our behalf, which would look something like:
const String add(const String &t1, const String &t2)
{
return t1 + t2;
}
显式实例化
调用模板函数时,编译器将先把正确的类型实例化模板。虽然标准允许显式模板实例化,然而并非所有厂商都能够正确地实例它。例如,Visual C++ 6.0 会潜在地调用错误的函数::
template<class T>
int getSize(void) {
return sizeof(T);
}
// 输出4,应该为8
cout << "double: " << getSize<double>() << endl;
// 输出4,正确
cout << "int: " << getSize<int>() << endl;
跨平台代码设计者不希望依赖于显式模板函数实例化,除非有更好的编译器能够对它提供有效的支持
C++模板概述
只有使用C++语言的少数用户才努力尝试去理解模板的基本原理。然而那些希望去探索更多高级用法的人往往发现自己需要努力去理解模板是如何被语言所支持的,因为缺乏明确的说明。一个很大的问题在于一些工具只实现了C++标准的一个子集。本文将指出它们共同的缺陷并深入剖析如何使用C++模板快速产生可重用和高效的代码。
模板功能应用的典型是通过一系列模板类形成的完整类库,特别是STL和ATL。标准C++库(STL)提供了很多可重用和灵活的类及算法,而ATL则是使用C++进行COM编程的事实标准。要掌握这些及其它的模板库,理解模板是如何工作的这一基础是非常重要的。
函数模板
int main()
{
0 cout<<add(2,3)<<endl;
1 cout<<add(2.1,3)<<endl;
2 cout<<add(2,3.2)<<endl;
3 cout<<add(2.2,3.3)<<endl;
4 cout<<add("hello eone ","world")<<endl;
return 0;
}
也可以通过宏定义#define add(a,b) ((a)+(b))来实现,但是指针(字符串)不能直接相加.对于2,3,4需要进行模板特化.
通过重载函数,我们能够完成多种不同数据类型的相同操作。要实现两个double数值的加法和两个整数类型的加法,我们可以使用一个重载函数:
int add(const int x, const int y)
{
return x + y;
}
double add(const double x, const double y)
{
return x + y;
}
这时,编译器将根据它们的参数正确地解决这一问题。
// 调用int add(const int, const int);
const int z1 = add(3, 2);
// 调用double add(const double, const double);
const double z2 = add(3.0, 2.0);
如果我们需要处理其它类型,我们就不得不提供其他函数重载。对每个不同的数据类型实现一个函数重载,它们都遵循相同的模式,每当我们需要调用针对某一数据类型的函数时,原则上编译器为我们生成相应的代码。而一个模板函数则以如下方式实现:
template<class T>
const T add(const T &t1, const T &t2)
{
return t1 + t2;
}
从概念上来说,编译器通过模板关键字(后面跟随着模板由一或多个模板参数构成的参数列表)来识别模板。当为某一具体类型调用add时,编译器将根据模板定义并用给定的类型替换出现在模板中的参数。在这个例子中,模板参数列表由一个独立的类型模板参数T构成。使用一个模板函数替代函数重载,编译器可以自动为所需的新类型生成代码
我们可以对任何拥有+操作符定义的类型使用add模板。假设一个自定义的String类提供了字符串连接并知道如何将自身写入到std::ostream。因为String与该模板函数兼容,因此我们可以调用它来实现字符串相加:
// 示例字符串
const string strBook("book");
const string strWorm("worm");
// 显示 "bookworm".
cout << add(strBook, strWorm) << endl;
Seeing that we intended to add two String values, the compiler will generate the appropriate add function on our behalf, which would look something like:
const String add(const String &t1, const String &t2)
{
return t1 + t2;
}
显式实例化
调用模板函数时,编译器将先把正确的类型实例化模板。虽然标准允许显式模板实例化,然而并非所有厂商都能够正确地实例它。例如,Visual C++ 6.0 会潜在地调用错误的函数::
template<class T>
int getSize(void) {
return sizeof(T);
}
// 输出4,应该为8
cout << "double: " << getSize<double>() << endl;
// 输出4,正确
cout << "int: " << getSize<int>() << endl;
跨平台代码设计者不希望依赖于显式模板函数实例化,除非有更好的编译器能够对它提供有效的支持
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
2013-07-25
展开全部
LZ应该先从字面意思去理解,什么是模板,中文意思应该相当清楚了.
T的意思是可以代表任何类型.我建议在VC里写几行代码.
C++没有模板就失去了一半的魅力了.ATL,MFC,STL,WTL都用到了模板.模板非常重要的.至少会用.
T的意思是可以代表任何类型.我建议在VC里写几行代码.
C++没有模板就失去了一半的魅力了.ATL,MFC,STL,WTL都用到了模板.模板非常重要的.至少会用.
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐于2016-09-06
展开全部
C++中模板的声明和定义的位置一定要小心处理, 否则在链接时会出现"无法解析某某函数或类"的错误。
函数模板的一般定义形式:
template < 类型形式参数表 > 返回类型 FunctionName( 形式参数表 )
{
// 函数定义体
}
说明:
⒈ < 类型形式参数表 > 可以包含基本数据类型,也可以包含类类型。若是类类型,则须加前缀 class 。
⒉这样的函数模板定义不是一个实实在在的函数,编译系统不为其产生任何执行代码。该定义只是对函数的描述,表示它每次能单独处理在类型形式参数表中说明的数据类型。
函数模板的一般定义形式:
template < 类型形式参数表 > 返回类型 FunctionName( 形式参数表 )
{
// 函数定义体
}
说明:
⒈ < 类型形式参数表 > 可以包含基本数据类型,也可以包含类类型。若是类类型,则须加前缀 class 。
⒉这样的函数模板定义不是一个实实在在的函数,编译系统不为其产生任何执行代码。该定义只是对函数的描述,表示它每次能单独处理在类型形式参数表中说明的数据类型。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
2013-07-25
展开全部
若一个程序的功能是对某种特定的数据类型进行处理,则将所处理的数据类型说明为参数,就可以把这个程序改写为模板。 C++ 程序由类和函数组成,所以 C++ 的模板也分为类模板和函数模板。
1、 函数模板的定义:
�6�1 函数模板的一般定义形式:
template < 类型形式参数表 > 返回类型 FunctionName( 形式参数表 )
{
// 函数定义体
}
�6�1 说明:⒈ < 类型形式参数表 > 可以包含基本数据类型,也可以包含类类型。若是类类型,则须加前缀 class 。
���� ⒉这样的函数模板定义不是一个实实在在的函数,编译系统不为其产生任何执行代码。该定义只是对函数的描述,表示它每次能单独处理在类型形式参数表中说明的数据类型。
���� ⒊当编译系统发现有一个函数调用: FunctionName( 实在参数表 ); 将根据实在参数表中的类型,确认是否匹配函数模板中对应的形式参数表,然后生成一个重载函数。该重载函数的定义体和函数模板的函数定义体相同,而形式参数表的类型则以实在参数表的实际类型为依据。该重载函数称为模板函数。
�6�1 函数模板与模板函数的区别:
函数模板是模板的定义,定义中用到通用类型参数。
模板函数是实实在在的函数定义,它由编译系统在碰见具体的函数调用时所生成,具有程序代码。
例 1 : #include<iostream.h>
template <class T> T Max(T&a,T&b)
T max(T a,T b)
{
return a>b?a:b;
}
void main()
{
cout<<”Max(3,5) is”<<Max(3,5)<<endl;
cout<<”Max(‘ 3' ,' 5' ) is:<<Max(‘ 3' ,' 5' )<<endl;
}
运行结果为: Max(3,5) is 5
Max(‘ 3' ,' 5' ) is 5
分析:当编译程序发现 Max(3,5) 调用时,它就产生一个如下一个函数定义,生成其程序代码:
int Max(int a,int b)
{
return a>b?a:b;
}
当发现 Max(‘ 3' ,' 5' ) 调用时,它又产生另一个如下的函数定义,也生成其程序代码:
char Max(char a,char b)
{
return a>b?a:b;
}
这样实参是什么数据类型,返回值也是什么类型,避免了相同操作的重载定义。
另外可以象重载普通函数那样重载模板函数。
例 2 : #include<iostream.h>
#include<string.h>
template <class T> T max(T a,T b)
{
return a>b?a:b;
}
char *max(char *a,char *b)
{
return (strcmp(a,b)?a:b);
}
void main()
{
cout<<”Max(\”hello\”,\”gold\” is “<<max(“hello”,”gold”)<<endl;
}
��函数 char *max(char *,char *) 中的名字 max 与函数模板的名字相同,但操作不同,这种情况就是重载模板函数。编译程序在处理这种情况时,首先匹配重载函数,然后再寻求模板的匹配。该程序中, max(“hello”,”gold”) 调用,匹配了非模板函数 char *(char *,char *) 。
2、类模板的定义:
�6�1 类模板的一般定义形式:
template< 类型形式参数表 > class classname
{
// 类声明体
}
template < 类型形式参数表 > 返回类型 classname< 类型名表 >::MemberFunctionname1( 形式参数表 )
{
// 成员函数定义体
}
template < 类型形式参数表 > 返回类型 classname< 类型名表 >::MemberFunctionname2( 形式参数表 )
{
// 成员函数定义体
}
template < 类型形式参数表 > 返回类型 classname< 类型名表 >::MemberFunctionnamen( 形式参数表 )
{
// 成员函数定义体
}
�6�1 说明:⒈其中的类型形式参数表与函数模板中的意义
一样。后面的成员函数定义中, classname< 类型名表 > 中的类型名表是类型形式参数的使用。
⒉这种类模板的定义其实只是对类的描述,不是具体的类。
⒊建立类模板后,可以通过创建类模板的实例来使用该类模板。
Classname < 类型实在参数表 > object;
�6�1 类模板与模板类的区别:
类模板是模板的定义,不是一个实在的类, 定义中用到通用类型参数。
模板类是实在的类定义,是类模板的实例化。类定义中参数被实际类型所代替。
例 3 :定义一个单向链表的模板类,它分别实现增加、删除、寻找和打印操作。
#include <iostream.h>
template<class T>class List
{
public:
List();
Void Add(T&);
Void Remove(T&);
T* Find(T&);
Void printList();
~List();
private:
struct Node{
Node *pNext;
T *pT;
};
Node *pFirst;
}
template<class T> List <T>::List()
{
pFirst=0;
}
template<class T> void List<T>::Add(T&t)
{
node *temp=new Node;
temp->pT=&t;
temp->pNext=pFirst;
pFirst=temp;
}
1、 函数模板的定义:
�6�1 函数模板的一般定义形式:
template < 类型形式参数表 > 返回类型 FunctionName( 形式参数表 )
{
// 函数定义体
}
�6�1 说明:⒈ < 类型形式参数表 > 可以包含基本数据类型,也可以包含类类型。若是类类型,则须加前缀 class 。
���� ⒉这样的函数模板定义不是一个实实在在的函数,编译系统不为其产生任何执行代码。该定义只是对函数的描述,表示它每次能单独处理在类型形式参数表中说明的数据类型。
���� ⒊当编译系统发现有一个函数调用: FunctionName( 实在参数表 ); 将根据实在参数表中的类型,确认是否匹配函数模板中对应的形式参数表,然后生成一个重载函数。该重载函数的定义体和函数模板的函数定义体相同,而形式参数表的类型则以实在参数表的实际类型为依据。该重载函数称为模板函数。
�6�1 函数模板与模板函数的区别:
函数模板是模板的定义,定义中用到通用类型参数。
模板函数是实实在在的函数定义,它由编译系统在碰见具体的函数调用时所生成,具有程序代码。
例 1 : #include<iostream.h>
template <class T> T Max(T&a,T&b)
T max(T a,T b)
{
return a>b?a:b;
}
void main()
{
cout<<”Max(3,5) is”<<Max(3,5)<<endl;
cout<<”Max(‘ 3' ,' 5' ) is:<<Max(‘ 3' ,' 5' )<<endl;
}
运行结果为: Max(3,5) is 5
Max(‘ 3' ,' 5' ) is 5
分析:当编译程序发现 Max(3,5) 调用时,它就产生一个如下一个函数定义,生成其程序代码:
int Max(int a,int b)
{
return a>b?a:b;
}
当发现 Max(‘ 3' ,' 5' ) 调用时,它又产生另一个如下的函数定义,也生成其程序代码:
char Max(char a,char b)
{
return a>b?a:b;
}
这样实参是什么数据类型,返回值也是什么类型,避免了相同操作的重载定义。
另外可以象重载普通函数那样重载模板函数。
例 2 : #include<iostream.h>
#include<string.h>
template <class T> T max(T a,T b)
{
return a>b?a:b;
}
char *max(char *a,char *b)
{
return (strcmp(a,b)?a:b);
}
void main()
{
cout<<”Max(\”hello\”,\”gold\” is “<<max(“hello”,”gold”)<<endl;
}
��函数 char *max(char *,char *) 中的名字 max 与函数模板的名字相同,但操作不同,这种情况就是重载模板函数。编译程序在处理这种情况时,首先匹配重载函数,然后再寻求模板的匹配。该程序中, max(“hello”,”gold”) 调用,匹配了非模板函数 char *(char *,char *) 。
2、类模板的定义:
�6�1 类模板的一般定义形式:
template< 类型形式参数表 > class classname
{
// 类声明体
}
template < 类型形式参数表 > 返回类型 classname< 类型名表 >::MemberFunctionname1( 形式参数表 )
{
// 成员函数定义体
}
template < 类型形式参数表 > 返回类型 classname< 类型名表 >::MemberFunctionname2( 形式参数表 )
{
// 成员函数定义体
}
template < 类型形式参数表 > 返回类型 classname< 类型名表 >::MemberFunctionnamen( 形式参数表 )
{
// 成员函数定义体
}
�6�1 说明:⒈其中的类型形式参数表与函数模板中的意义
一样。后面的成员函数定义中, classname< 类型名表 > 中的类型名表是类型形式参数的使用。
⒉这种类模板的定义其实只是对类的描述,不是具体的类。
⒊建立类模板后,可以通过创建类模板的实例来使用该类模板。
Classname < 类型实在参数表 > object;
�6�1 类模板与模板类的区别:
类模板是模板的定义,不是一个实在的类, 定义中用到通用类型参数。
模板类是实在的类定义,是类模板的实例化。类定义中参数被实际类型所代替。
例 3 :定义一个单向链表的模板类,它分别实现增加、删除、寻找和打印操作。
#include <iostream.h>
template<class T>class List
{
public:
List();
Void Add(T&);
Void Remove(T&);
T* Find(T&);
Void printList();
~List();
private:
struct Node{
Node *pNext;
T *pT;
};
Node *pFirst;
}
template<class T> List <T>::List()
{
pFirst=0;
}
template<class T> void List<T>::Add(T&t)
{
node *temp=new Node;
temp->pT=&t;
temp->pNext=pFirst;
pFirst=temp;
}
本回答被网友采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询