我是C ++模板的新手,我发现很难理解和调试它们。这两个/两者都有什么好的资源?
答案 0 :(得分:9)
我推荐Vandevoorde和Josuttis出版的优秀书籍C++ Templates - The Complete Guide。
答案 1 :(得分:4)
Alexandrescu是一个模板向导。他有很多文章(其中许多可以在他的网站和其他网站上免费获得)和一些书籍。
Boost Documentation和Boost Cookbook是一个很好的网站,一旦您对模板感到满意并感觉自己想要升级为Boost就可以了。
答案 2 :(得分:1)
模板只是减少开发类时需要编写的代码量的一种方法。
例如STL向量
std::vector<int> intList;
std::vector<float> floatList;
这将导致编译器在幕后实际创建两个类,类似于复制和粘贴代码但用float替换所有对int的引用。
如果没有模板,您需要为要处理的每种类型创建一个矢量类。类有更复杂的用途,但这是最容易使用,创建和使用的类。理解。
编译后,vector<int>
和vector<float>
的两组代码完全独立,但IDE会在调试时逐步执行模板类。
答案 3 :(得分:1)
我有两个快速提示,可以在将来为您节省一些问题。
模板必须在标头中定义和实施,因为它们是在编译时翻译/创建的
如果您有以下代码:
// Foo.h
template <typename T>
class Foo
{
...
};
// Bar.cpp
#include "Foo.h"
void func()
{
Foo<int> fooInt;
Foo<double> fooDouble;
}
当处理Bar.cpp文件时,编译器将“创建”Foo类的新定义,每个T替换为fooInt实例的int类型,以及Foo类的新定义,每个T替换为fooDouble实例的double类型。
简而言之,C ++不支持模板类,编译器模拟它们在编译时替换类型并创建普通类。因此,fooInt和fooDouble的编译类型是不同的。
因为它们是在编译时翻译而不是单独编译的,所以必须在标题中定义和实现。
如果将模板类实现为普通类(头文件和源文件),编译器(实际上是链接器)抛出的错误是没有实现任何方法(这是因为忽略了源文件)。
您仍然可以创建前向声明以避免循环依赖
只是你必须转发声明它们:
template <typename T>
class Foo;
并且,与正常的前向声明一样,您必须确保包含所有必需的标头。
答案 4 :(得分:0)
他们可以根据需要进行扩展和修改。请记住,这是一个模板,而不是解决方案。
HTH
答案 5 :(得分:-1)
这是一篇非常好的,近乎简洁的文章来了解c ++模板 http://www.codeproject.com/Articles/257589/An-Idiots-Guide-to-Cplusplus-Templates-Part
我将在这里带来必要的部分:
1.function templates:
简单的功能模板:
template<class TYPE>
void PrintTwice(TYPE data)
{
cout<<"Twice: " << data * 2 << endl;
}
请注意&#34; TYPE&#34;可以是任何其他有效名称。
您最好使用反映type-parameter含义的名称,这样可以提高代码的可读性。
现在你可以这样称呼它:
PrintTwice(5.5);//TYPE is 'float'
PrintTwice(5);//TYPE is 'int'
您可以强制编译器为您明确传递的类型实例化函数:
PrintTwice<double>(5);
如果你没有传递任何类型,编译器会确定类型是什么。
你可以拥有多个参数的模板和(可选)返回类型相同的类型:
template<class T>
T Add(T n1, T n2)
{
return n1 + n2;
}
但请注意,例如,您无法在n1
和int
中传递n2
!两个参数应该是相同的类型,返回类型也是该类型。
如果你想拥有一个可能不同类型参数的模板函数:
template<class T1, class T2>
double Add(T1 t1Data, T2 t2Data)
{
return t1Data + t2Data;
}
并使用它:
cout<<Add(5,7.0);//T1=int T2=double
cout<<Add(5.5,7);//T1=double T2=int
cout<<Add<double,double>(5,7);//T1=double T2=double by passing types explicitly
当function-template采用template-type,但不是来自其函数参数,如:
template<class T>
void PrintSize()
{
cout << "Size of this type:" << sizeof(T);
}
您不能简单地将此类功能模板称为:
PrintSize();
由于此函数模板需要模板类型参数规范,因此编译器无法自动推导出。正确的电话会是:
PrintSize<float>();
2.class模板:
定义几乎相似:
template<class T>
class Item
{
T Data;
public:
Item() : Data( T() )
{}
void SetData(T nValue)
{
Data = nValue;
}
T GetData() const
{
return Data;
}
void PrintData()
{
cout << Data;
}
};
但在使用它时,您应该明确指定类型:
Item<int> item1;
棘手的部分是,你不能在头文件中实现声明,以及在一个或多个源文件中的相应实现。(请参阅文章了解原因)
类模板也允许很少的非类型模板参数:
template<class T, int SIZE>
class Array
{
static const int Elements_2x = SIZE * 2;
void DoSomething(int arg = SIZE);
// Non-const can also appear as default-argument...
private:
T TheArray[SIZE];
};
还有很多其他部分和更多的解释,我无法带来。
我建议你花几个小时阅读那篇文章和那篇文章的第二部分。即使你认为你知道模板如何在c ++中工作。