互联网@时事传播诗歌专集诗歌

C++模板与泛型 --- 成员函数模板,显式实例化、声明

2019-05-15  本文已影响11人  307656af5a04

上一节我们学习了typename的使用场合、默认模板参数、趣味写法分析,通过上一节的学习,大家对typename的使用场合、默认模板参数、趣味写法分析有一个比较清晰的认识,那么本节,我们继续学习模板与泛型的知识,即t成员函数模板,显示实例化、声明,希望通过本节的学习,大家能够对模板与泛型的概念有一个更加清晰的认识!

一、普通类的成员函数模板

不管是普通类,还是模板类,它的成员函数可以是一个函数模板,称为"成员函数模板",但是这个函数不可以是虚函数,否则,编译器会报错。

class A // 普通类
{
public:
    template <typename T>
    // 成员函数模板
    void myft(T tmpt)  
    {
        cout << tmpt << endl;
    }
};

int main()
{
    A a;
    // 编译器在遇到这条语句时,
    // 编译器就会实例化这个函数模板
    a.myft(3);
}

二、类模板的成员函数模板

类模板的模板参数必须用<>指定,成员函数模板、普通函数模板的参数都可以推断出来;
类模板的成员函数(包括普通成员函数/成员函数模板)只有为程序所用,才会实例化;如果函数从未使用,则不会实例化该成员函数。

#include <iostream>
using namespace std;

// 类模板的参数
template <typename C> 
class A // 普通类
{
public:
    // 构造函数模板
    // 与整个类的模板没有关系
    template <typename T2>
    A(T2 v1, T2 v2);    

    template <typename T>
    // 成员函数模板
    void myft(T tmpt)  
    {
        cout << tmpt << endl;
    }

    // 普通成员函数
    void myfun(){   }

    C m_ic; // 类模板变量
};

// 先跟类的模板参数列表
template <typename C>
// 再跟构造函数自己的模板参数列表
template <typename T2>
A<C>::A(T2 v1, T2 v2)
{
    cout << v1 << v2 << endl;
}

int main()
{
    A<float> a(1, 2);

    A<float> b(1.1, 2.2);

    return 0;
}

三、模板显式实例化,模板声明

为了防止多个.cpp文件中都实例化相同的类模板,所以C++11提出了一个解决方法,我们称为"显式实例化";通过"显式实例化"避免生成多个相同类模板实例的开销。

模板的实例化定义只有一个,模板的实例化声明可以有多个。

实例

ca.h

#pragma once
#ifndef __CAH__
#define __CAH__

#include <iostream>

// 类模板的参数
template <typename C>
class A // 普通类
{
public:
    // 构造函数模板
    // 与整个类的模板没有关系
    template <typename T2>
    A(T2 v1, T2 v2);

    template <typename T>
    // 成员函数模板
    void myft(T tmpt)
    {
        cout << tmpt << endl;
    }

    // 普通成员函数
    template <typename T2>
    void myfunc(T2 v1, T2 v2);

    C m_ic; // 类模板变量
};

// 先跟类的模板参数列表
template <typename C>
// 再跟构造函数自己的模板参数列表
template <typename T2>
A<C>::A(T2 v1, T2 v2)
{
    cout << v1 << v2 << endl;
}

template <typename T>
void mfunc123(T v1, T v2)
{
    cout << v1 + v2 << endl;
}

#endif

ca.cpp

#include "ca.h"

using namespace std;

// 显式实例化手段中的实例化定义,这种实例化只需在一个.cpp
// 文件中写就可以
// 编译器遇到这段代码就直接实例化一个A<float>
template A<float>; 

void mfunc()
{
    A<float> a(1, 2);
}

// 先跟类的模板参数列表
template <typename C>
// 再跟构造函数自己的模板参数列表
template <typename T2>
void A<C>::myfunc(T2 v1, T2 v2)
{

}

// 编译器会为其生成代码
template void mfunc123(int v1, int v2);  

main.cpp

#include <iostream>
#include "ca.h"

using namespace std;

// 显式实例化手段中的"实例化声明"
// 其他所有.cpp文件用到这个类型的话都这么写
// 在一个文件中实例化,其他文件全部为声明
// extern template A<float>;
// extern作用:不会在在本文件中生成一个extern后面所表示的模板的实例化代码
// extern目的:告诉编译器,在其他的源文件(.cpp)中已经有了一个改该模板的实例化版本了。
extern template A<float>;

// 显式声明函数模板
extern template void mfunc123(int v1, int v2);

int main()
{
    A<float> a(1, 2);

    A<float> b(1.1, 2.2);

    return 0;
}

我是奕双,现在已经毕业将近两年了,从大学开始学编程,期间学习了C需要编程,C++需要编程,Win32编程,MFC编程,毕业之后进入一家图像处理相关领域的公司,掌握了用OpenCV对图像进行处理,如果大家对相关领域感兴趣的话,可以关注我,我这边会为大家进行解答哦!如果大家需要相关学习资料的话,可以私聊我哦!

上一篇 下一篇

猜你喜欢

热点阅读