010 模板函数和类

 

/*
目录:
一: 模板函数
    1 重复函数 - 暂时
    2 函数模板 - 设计
    3 函数模板 - 原理
二: 模板类
    1 类内编写
    2 类外编写
*/

 

一: 模板函数
  1 重复函数

#include "stdafx.h"

using namespace std;

void swap(int &a, int &b)
{
    int t = a;
    a = b;
    b = t;
}

void swap(float &a, float &b)
{
    float t = a;
    a = b;
    b = t;
}

void swap(double &a, double &b)
{
    double t = a;
    a = b;
    b = t;
}

int main(int argc, char *argv[], char **envp)
{
    int nNum1 = 3, nNum2 = 4;
    float fNum1 = 3.1, fNum2 = 4.2;
    double dNum1 = 3.11, dNum2 = 4.22;

    // 类型 - int
    printf("nNum1 = %d; nNum2 = %d\n", nNum1, nNum2);
    swap(nNum1, nNum2);
    printf("nNum1 = %d; nNum2 = %d\n\n", nNum1, nNum2);

    // 类型 - float
    printf("fNum1 = %0.2f; fNum2 = %0.2f\n", fNum1, fNum2);
    swap(fNum1, fNum2);
    printf("fNum1 = %0.2f; fNum2 = %0.2f\n\n", fNum1, fNum2);


    // 类型 - double
    printf("dNum1 = %0.2f; dNum2 = %0.2f\n", dNum1, dNum2);
    swap(dNum1, dNum2);
    printf("dNum1 = %0.2f; dNum2 = %0.2f\n", dNum1, dNum2);

    return 0;
}

1 : 同步骤,不同类型的函数,需要编写三个函数,好麻烦。

 

  2 函数模板 - 设计

#include "stdafx.h"

using namespace std;

template<class T>
void swap(T &a, T &b)
{
    T t = a;
    a = b;
    b = t;
}

int main(int argc, char *argv[], char **envp)
{
    int nNum1 = 3, nNum2 = 4;
    float fNum1 = 3.1, fNum2 = 4.2;
    double dNum1 = 3.11, dNum2 = 4.22;

    // 类型 - int
    printf("nNum1 = %d; nNum2 = %d\n", nNum1, nNum2);
    swap<int>(nNum1, nNum2);
    printf("nNum1 = %d; nNum2 = %d\n\n", nNum1, nNum2);

    // 类型 - float
    printf("fNum1 = %0.2f; fNum2 = %0.2f\n", fNum1, fNum2);
    swap<float>(fNum1, fNum2);
    printf("fNum1 = %0.2f; fNum2 = %0.2f\n\n", fNum1, fNum2);


    // 类型 - double
    printf("dNum1 = %0.2f; dNum2 = %0.2f\n", dNum1, dNum2);
    swap<double>(dNum1, dNum2);
    printf("dNum1 = %0.2f; dNum2 = %0.2f\n", dNum1, dNum2);

    return 0;
}

1 : 把类型提取出来,流程通用,把三个函数转为一个模板,方便多了。

 

  3 函数模板 - 原理

   23:     swap<int>(nNum1, nNum2);
004168D5  lea         eax,[nNum2]  
004168D8  push        eax  
004168D9  lea         ecx,[nNum1]  
004168DC  push        ecx  
004168DD  call        swap<int> (0411005h)  
004168E2  add         esp,8 

00411005  jmp         swap<int> (0411990h)     // 函数地址 - int类型

    8: void swap(T &a, T &b)
     9: {
00411990  push        ebp  
00411991  mov         ebp,esp  
00411993  sub         esp,0CCh  
00411999  push        ebx  
0041199A  push        esi  
0041199B  push        edi  
0041199C  lea         edi,[ebp-0CCh]  
004119A2  mov         ecx,33h  
004119A7  mov         eax,0CCCCCCCCh  
004119AC  rep stos    dword ptr es:[edi]  
    10:     T t = a;
004119AE  mov         eax,dword ptr [a]  
004119B1  mov         ecx,dword ptr [eax]  
004119B3  mov         dword ptr [t],ecx  
    11:     a = b;
004119B6  mov         eax,dword ptr [a]  
004119B9  mov         ecx,dword ptr [b]  
004119BC  mov         edx,dword ptr [ecx]  
004119BE  mov         dword ptr [eax],edx  
    12:     b = t;
004119C0  mov         eax,dword ptr [b]  
004119C3  mov         ecx,dword ptr [t]  
004119C6  mov         dword ptr [eax],ecx  
    13: }
004119C8  pop         edi  
    13: }
004119C9  pop         esi  
004119CA  pop         ebx  
004119CB  mov         esp,ebp  
004119CD  pop         ebp  
004119CE  ret  

 

 28:     swap<float>(fNum1, fNum2);
00416921  lea         eax,[fNum2]  
00416924  push        eax  
00416925  lea         ecx,[fNum1]  
00416928  push        ecx  
00416929  call        swap<float> (04114B5h)  
0041692E  add         esp,8  

004114B5  jmp         swap<float> (04119D0h)    // 函数地址 - float类型


    7: template<class T>
     8: void swap(T &a, T &b)
     9: {
004119D0  push        ebp  
004119D1  mov         ebp,esp  
004119D3  sub         esp,0CCh  
004119D9  push        ebx  
004119DA  push        esi  
004119DB  push        edi  
004119DC  lea         edi,[ebp-0CCh]  
004119E2  mov         ecx,33h  
004119E7  mov         eax,0CCCCCCCCh  
004119EC  rep stos    dword ptr es:[edi]  
    10:     T t = a;
004119EE  mov         eax,dword ptr [a]  
004119F1  movss       xmm0,dword ptr [eax]  
004119F5  movss       dword ptr [t],xmm0  
    11:     a = b;
004119FA  mov         eax,dword ptr [a]  
004119FD  mov         ecx,dword ptr [b]  
00411A00  mov         edx,dword ptr [ecx]  
00411A02  mov         dword ptr [eax],edx  
    12:     b = t;
00411A04  mov         eax,dword ptr [b]  
00411A07  movss       xmm0,dword ptr [t]  
00411A0C  movss       dword ptr [eax],xmm0  
    13: }
00411A10  pop         edi  
    13: }
00411A11  pop         esi  
00411A12  pop         ebx  
00411A13  mov         esp,ebp  
00411A15  pop         ebp  
00411A16  ret 

1 : 函数类型int跳转地址: jmp  swap<int> (0411990h); 

2 : 函数类型float跳转地址: jmp  swap<float> (04119D0h) 

3 : 不同类型的函数实际拥有不同的地址,程序逻辑和大小没有改变,方便了程序员编写代码,让代码更简洁。

 

二: 模板类
  1 类内编写

// Complex.h
#pragma once
#include <iostream>

template<class DATA>

class CCmoplex
{
public:
    CCmoplex() : m_fReal(0), m_fImag(0)
    {
    }

    CCmoplex(DATA fReal, DATA fImag) : m_fReal(fReal), m_fImag(fImag)
    {
    }

    void Print()
    {
        cout << m_fReal << "\t" << m_fImag << endl;
    }

private:
    DATA m_fReal, m_fImag;
};
#include "stdafx.h"
#include "Complex.h"

using namespace std;
int main(int argc, char *argv[], char **envp)
{
    CCmoplex<int> nNum(2, 3);
    nNum.Print();

    CCmoplex<double> dNum(2.2, 3.3);
    dNum.Print();

    return 0;
}

 

  2 类外编写

#pragma once
#include <iostream>


template<typename DATA>
class CCmoplex
{
public:
    CCmoplex();
    CCmoplex(DATA fReal, DATA fImag);

    void Print();

private:
    DATA m_fReal, m_fImag;
};

template<typename DATA>
CCmoplex<DATA>::CCmoplex():m_fReal(0), m_fImag(0)
{
}

template<typename DATA>
CCmoplex<DATA>::CCmoplex(DATA fReal, DATA fImag) : m_fReal(fReal), m_fImag(fImag)
{
}

template<typename DATA>
void CCmoplex<DATA>::Print()
{
    cout << m_fReal << "\t" << m_fImag << endl;
}

 

posted @ 2019-10-07 13:43  火焰马  阅读(237)  评论(0编辑  收藏  举报