模板

数据类型参数化——模板。模板说明的类属参数必须在函数定义中至少出现一次,函数模板定义由模板说明和函数定义组成。

template <class T1,class T2,class T3>

void fun(T1 a , T2 b)
{
       a > b? a:b;    
    
}

//编译出错,没有用到T3

 

泛型编程函数的使用方法:

1、自动类型推导

2、具体类型调用

template <typename T>
void swap(T& x,T& y)
{
    T mid = x;
    y = x;
    x= mid;
}
void main()
{
    int result = swap(1,2);                //自动推导
    int result_2 = swap <int> (1,2);    //显示调用
}

函数模板遇上函数重载:

函数模板不能完成参数的隐式转换。函数模板严格检查参数类型。

templete <typename T>
void myswap(T& x,T& y)
{
    T mid = x;
    y = x;
    x= mid;
}

void main()
{
    int result = swap(1,2);      //自动推导
    result = swap(1,'a');        //编译出错。 
}templete <typename T>
void myswap(T& x,T& y)
{
    T mid = x;
    y = x;
    x= mid;
}
void myswap(int& x,char& y)
{
    int mid = x;
    y = x;
    x= mid;
}
void main() { int result = myswap(1,2); //自动推导 result = myswap(1,'a'); //编译成立。 }

函数重载可以参与函数模板。

templete <typename T>
void myswap(T& x,T& y)
{
    T mid = x;
    y = x;
    x= mid;
}
void myswap(int& x,int& y)
{
    int mid = x;
    y = x;
    x= mid;
}

void main()
{
    int result = myswap(1,2);      
    result = myswap(1,'a');        //编译成立,'a'隐式转换为int类型
    
}

匹配约定:

首先找重载函数(根据参数类型直接匹配到对应函数),如果没有找到,则考虑模板函数,如果没有匹配到,则考虑隐式转换,再选择调用,隐式转换只能针对普通函数存在(换言之,模板函数不能考虑隐式转换调用)。

所以 上述的 result = myswap(1,2);调用的是 void myswap(int& ,int&);而不是调用模板函数。

如果非要调用模板函数呢?——使用显示调用模板方式:result = myswap<>(1,2);   "<>"可以为空。

 

函数模板的本质:

实际上编译器在函数调用时,会根据参数类型生成支持这种类型的函数,所以在实际调用函数时,只能针对性的调用某一个函数,而不能通过类型转换之后再考虑模板函数调用。

所以:模板函数会经过两次编译,第一次是在编译期时,对模板代码本身进行编译;第二次是在函数调用时,会根据参数类型生成相应的专门针对这种参数类型的函数(有几种情况,将会生成几个函数)。

 

 

类模板:类也可参数化。

类模板语法:模板说明+类说明

templete <typename T>
class A
{
    public:
        T getA()
        {
            return a;
        }
    private:
        T a;
};

void fun(A* p)
{
    cout<< p->getA()<<endl;    //编译出错 
}
void fun(A<int> *p)
{
    cout<< p->getA()<<endl;    //编译正确 
}

void main()
{
    A a1;    //编译出错,因为 类中成员变量或成员函数是抽象数据类型——T,并不知道到底是什么
    A <int> a2;    //编译成立
}
templete <typename T>
class A
{
    public:
        A(int a)
        {
            this->a = a;
        }
        ~A()
        {
            ;
        }
        T getA()
        {
            return a;
        }
    private:
        T a;
};

class B :public A<int>    //必须指明继承的父类类型
{
    public:
        B(int a,int b) :A<int>(a)    //父类带参
        {
            this->b = b;
        }
    private:
        int b;
};

void fun(A* p)
{
    cout<< p->getA()<<endl;    //编译出错 
}
void fun_2(A<int> *p)
{
    cout<< p->getA()<<endl;    //编译正确 
}

void fun_3(B* bc)
{
    cout<<bc->getA()<<endl;
}

void main()
{
    A a1;    //编译出错,因为 类中成员变量或成员函数是抽象数据类型——T,并不知道到底是什么
    A <int> a2;        //编译成立
    B b1(1,2);         //编译成立
    fun_3(&b1);        //编译成立
}

 

类模板遇上友元函数:友元函数在模板类外定义,是通不过的,因为模板类的两次编译问题存在。

templete <class T>
class complex
{
    public:
        complex(T Real=0,T Imag =0);
        void fun();
        friend complex operator+(complex& c1,complex& c2);
        friend complex operator-(complex& c1,complex& c2)
        {
            complex temp(c1.real+c2.real,c1.imag+c2.imag);
            return temp;
        }//编译通过,模板类中友元函数的定义放在类中
    private:
        T real,imag;
};

template <class T>
complex<T>::complex(T Real=0,T Imag=0)
{
    this->real = Real;
    this->imag = Imag;
}

template <class T>
complex<T> operator+(complex<T> &c1,complex<T> &c2)
{
    complex<T> tmp(c1.real+c2.real,c1.imag+c2.iamg);
    return tmp;
}//模板类中的友元函数在类外定义是通不过的

template <class T>
void complex<T>::fun()
{
    cout<<this->real<<this->imag<<endl;
}

void main()
{
    complex<float> c1(1.0,2.0);
    complex<float> c2(2.4,3.4);
    c1.print();
    complex<float> c3 = c1+c2;
    complex<float> c3 = c1-c2;
}

 

类模板遇到static成员:

templete <class T>
class complex
{
    public:
        complex(T Real=0,T Imag =0);
        void fun();
        static int m_a;
    private:
        T real,imag;
};

int complex:: m_a = 0;

template <class T>
complex<T>::complex(T Real=0,T Imag=0)
{
    this->real = Real;
    this->imag = Imag;
}


template <class T>
void complex<T>::fun()
{
    cout<<this->real<<this->imag<<endl;
}

void main()
{
    complex<int> a1(1,2);
    complex<int> a2(3,4);
    complex<int> a3(5,6);
    
    complex<float> b1(1.1,2.1);
    complex<float> b2(1.11,2.11);
    complex<float> b3(1.111,2.111);
}

complex<int>定义对象时,生成一个模板专门针对int类型,所有用该类定义的对象共享该类定义的static int a

complex<float>定义对象时,生成另一个模板专门针对float类型,所有用该类定义的对象共享该类定义的static int a 

既然是两个类,那么这里的static也是分开的,初始化时都是一样的。

template <class T>
class complex
{
    public:
        complex(T Real=0,T Imag =0);
        void fun();
        static int m_a;
    private:
        T real,imag;
};

template <class T>
int complex<T>:: m_a = 0;

template <class T>
complex<T>::complex(T Real=0,T Imag=0)
{
    this->real = Real;
    this->imag = Imag;
}


template <class T>
void complex<T>::fun()
{
    cout<<this->real<<this->imag<<endl;
}

void main()
{
    complex<int> a1(1,2); a1.m_a++;   cout<<a1.m_a<<endl;
    complex<int> a2(3,4); a2.m_a++;   cout<<a1.m_a<<endl;
    complex<int> a3(5,6);a3.m_a++;    cout<<a1.m_a<<endl;
    
    complex<float> b1(1.1,2.1);          b1.m_a++;   cout<<b1.m_a<<endl;
    complex<float> b2(1.11,2.11);        b2.m_a++;   cout<<b2.m_a<<endl;
    complex<float> b3(1.111,2.111);      b3.m_a++;   cout<<b3.m_a<<endl;

    getchar();
}

 

posted @ 2016-10-17 21:02  e-data  阅读(146)  评论(0)    收藏  举报