C ++模板的资源

时间:2009-04-28 12:13:25

标签: c++ templates

我是C ++模板的新手,我发现很难理解和调试它们。这两个/两者都有什么好的资源?

6 个答案:

答案 0 :(得分:9)

我推荐Vandevoorde和Josuttis出版的优秀书籍C++ Templates - The Complete Guide

答案 1 :(得分:4)

Alexandrescu是一个模板向导。他有很多文章(其中许多可以在他的网站和其他网站上免费获得)和一些书籍。

Boost DocumentationBoost 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;
}

但请注意,例如,您无法在n1int中传递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 ++中工作。