加载中……
C++ 模板知识总结

是什么

模板是范型编程的基础,范型编程呢,顾名思义,就是传递的参数类型广泛,不固定,函数或者类自适应参数类型的意思。听起来似乎没什么,但不管怎样,你一定记住,模板可牛逼着呢。
比如说定义了一个如下的函数模板:

template <T>
T add( T a, T b )
{
    return a + b;
}

这里的T 我们就可以理解为万能的数据类型,或者说数据类型的一个占位,当我们使用该函数时会根据参数类型自动适配。在这里,函数add可以进行这样的描述:
返回值类型为T,参数a类型为T,参数b类型为T,其中T为任意数据类型。

所以呢,我们再看如下两个调用:

cout << add( 1, 2 ) << endl; //?
cout << add( 1.2, 2.1 ) << endl; //?

通过上面的解释,我们应该也很容易猜出结果,add(1,2)传入整型数据,不难看出结果为3;而add(1.2,2.1)传入浮点型数据,结果为3.3。

怎样?简单吧。我们继续,但记住,万变不离其宗,核心永远还是在于范型。

函数模板

总结我们先前所说的,函数模板其实就是可以接受任意类型的函数。其格式为:

template <typename type>
ret_type func_name(arr_type_a arr_name_a, arr_type_b arr_name_b) {
    //函数主体
}

在这里type代表函数中所有指明类型为type的值都会自适应给定的类型。通常arr_type_a、arr_type_b、ret_type可以等于type,这样就可以实现自适应传参了。但值得注意的是:

template <typename type> 中的type只能被指定一种类型

比如对文章最开始的add函数模板进行如下调用,编译器将会报错:

int a = 1;float b = 2.1;
cout << add( a, b ) << endl; //不合法,T被指定两种类型

类模板

格式

相比函数模板,类模板则复杂得多,有很多需要留意的地方。其格式为:

template <typename type> 
class class_name { 
    //类主体 
};

定义

template <typename T> 
class Shape
{
public:
    void setH( T a )
    {
        h = a;
    }
    void setW( T a )
    {
        w = a;
    }

    T getS()
    {
        return h * w;
    }
protected:
    T h;
    T w;
};

函数解析如下:

类模板Shape定义T为自适应类型,并含有如下成员函数setH()、setW()、getS()以及被保护的属性h和w。其中setH()和setW()都有一个类型为T的参数,getS()返回值类型为T。

使用

Shape<float> A;
A.setH( 3.1 );
A.setW( 2.9 );
cout << A.getS() << endl;//?

这里定义了一个Shape的类A,并指定模板T为float,即模板重所有的T被替换为float。可以看出,最后的结果为3.1*2.9,若A被定义为:

Shape<int> A;
A.setH( 3.1 );
A.setW( 2.9 );
cout << A.getS() << endl;//?

则结果为2*3 = 6。

类模板的继承

与普通类的继承不同,类模板继承时如需要访问父类的变量,需要使用父类的类作用域限定符,否则会报“identifier not found”错误。比如子类Triangle:

template <typename T>
class Triangle: public Shape<T>
{
public:
    T getS()
    {
        return Shape<T>::h * Shape<T>::w / 2;
    }
    T getH();
    T getW()
    {
        return Shape<T>::w;
    }
};

template <typename T>
T Triangle::getH()
{
    return Shape<T>::h;
}

其他说明

typename与class

模板的定义有两种:

template <typename T>
template <class T>

其实这两种方式完全一样,不必纠结,但typename有另外一个作用:告诉编译器其后是一个类型而不是一个变量。比如:

typename A::a *elem;

该句表示声明一个与类A中变量a类型等同的指针elem。如果没有typename,编译器将会把A::a当作一个变量值处理。

示例代码

以下代码可以作为运行参考。

#include <iostream>

using namespace std;

template <typename T>
T add( T a, T b )
{
    return a + b;
}

template <typename T>
class Shape
{
public:
    void setH( T a )
    {
        h = a;
    }
    void setW( T a )
    {
        w = a;
    }

    T getS()
    {
        return h * w;
    }
protected:
    T h;
    T w;
};
template <typename T>
class Triangle: public Shape<T>
{
public:
    T getS()
    {
        return Shape<T>::h * Shape<T>::w / 2;
    }
    T getH();
    T getW()
    {
        return Shape<T>::w;
    }
};

template<typename T>
T Triangle<T>::getH()
{
    return Shape<T>::h;
}

int main()
{
    {
        Shape<float> A;
        A.setH( 3.2 );
        A.setW( 2 );
        cout << A.getS() << endl;
    }
	 
    cout << add( 1, 2 ) << endl;
    cout << add( 1.2, 2.1 ) << endl;
    Shape<float> A;
    A.setH( 3.1 );
    A.setW( 2.9 );
    cout << A.getS() << endl;
    Triangle<int> B;
    B.setH( 31 );
    B.setW( 10 );
    cout << B.getW() << endl;
    cout << B.getH() << endl;
    cout << B.getS() << endl;
    return 0;
}
版权声明: 若无特殊说明,文章均为原创,版权归本文作者所有,转载请保留出处和此说明!
本文链接: C++ 模板知识总结
本文作者: Jan.
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇