C++笔记(七)

1.函数模板和类模板
     函数:返回值,函数名,函数参数列表
     函数形参列表:变量(变量类型)(变量名(值))
   (1)void mySwap(char &a1,char &a2)...
        void mySwap(double &a1,double &a2)...
        void mySwap(int &a1,int &a2)...
   (2)变量类型能否作为参数传递?
 -----> 怎样将变量的类型作为参数传递?
 -----> 模板
        a:写一个普通函数
          void Swap(char &a1,char &a2)...
        b:将类型参数化:template (用来声明模板)<>(类型参数列表)
          template <typename T>
          void Swap(T &a1,T &a2)...
    (3)Swap(a,b);//隐式调用,编译器会自己判断传过去的参数类型
         Swap<double>(a,b)//显式调用,<变量类型>




2.模板使用
   模板:将类型参数化--->将数据类型和数据本身进行分离
   算法:将不必关心处理的是什么类型的数据
         template <typename T,typename T1>
         void mySort(T arr[],T1 len)...


#include <iostream>


using namespace std;


template <typename T>
void Swap(T &a,T &b)
{
T temp = a;
a = b;
b = temp;
}


template <typename T>
void bubble(T arr[],int len)
{
for(int i = 0;i < len-1;i++)
{
for(int j = 0;j < len-i-1;j++)
{
if(arr[j] > arr[j+1])
{
Swap(arr[j] , arr[j+1]);
}
}
//print(arr,len);
}


}


template <typename T>
void print(T arr[],int len)
{
for(int i = 0;i < len;i++)
{
cout << arr[i] << " ";
}
cout << endl;
}


int main()
{
int arr[] = {10,9,8,7,6,5,4,3,2,1};
int len = sizeof(arr)/sizeof(arr[0]);
bubble<int>(arr,len);
print(arr,len);
 
char a[] = "wedfgasdghadsdfgnhmjawesrthym";
len = sizeof(a)/sizeof(a[0]);
bubble<char>(a,len-1);
print(a,len);


double b[] = {1.2,-3.4,5.6,-7.8,9.0};
len = sizeof(b)/sizeof(b[0]);
bubble<double>(b,len);
print(b,len);


return 0;
}




3.模板使用的注意事项
       (1)a: 
               void mySwap(int &a,int &b)...
 
               template <typename T>
               void Swap(T &a,T &b)...


               int a;
               char c;
               mySwap(a,c);//普通函数在参数传递的时候,可以进行参数的隐式转换
               Swap(a,c);//模板函数不行,模板不支持隐式数据类型转换
               print<int>(a,c);//非要用模板函数时
            b:在普通函数和函数模板都可以调用的情况下,优先调用普通函数
            c:print<>(a,b);//可以用空的参数列表<>来强制调用函数模板


       (2)函数模板可以被重载
            void print(T a,T b)...
            void print(T a,T b,T c)...
       (3)其实使用了函数模板,每种数据类型的函数并没有省略,只是由编译器自己来帮助补全的。
            template <typename T>
            void Swap(T &a,T &b)...
            //下面这些函数全由编译器补全
            void Swap(char &a,char &b)...
            void Swap(int &a,int &b)...
            void Swap(double &a,double &b)...


4.类模板
      (1)类的模板
            template <typename T>
            class Complex
            {
             public:
                  Complex(T a,T b)
                  {
                     this->a = a;
                     this->b = b;
                  }
             private:
                 T a;
                 T b;
             }
    
      (2)A:类模板去定义对象,必须要指明类型
             Complex<int>a1(1,2);
             Complex<double>b1(1.2,2.3);
           B:对象做参数传递:
                           a:指明对象类型
                           b:定义成模板
             void print(Complex<int>&a1)...//普通函数


             template<typename T>
             void print(Complex<T>&b1)...//模板函数


   
      (3)派生类
           A:派生自一个具体的类
             class A:public Complex<int>...
           B:派生一个类模板
             template <typename T>
            1.class B:public Complex<int>...
            2.class B:public Complex<T>...


5.类模板使用:所有的类模板函数写在类的内部


#include <iostream>


using namespace std;


template <typename T>
class Complex
{  
        //<1>
friend ostream &operator<<(ostream &out,Complex<T> &a3)
{
out << a3.a << "+" << a3.b << "i";
return out;
}//有friend修饰,所以它是一个外部函数,不是类的内部函数,但是不能就这样将函数写在类的外部,编译不通过
        /*<2>
friend Complex<T> operator+(Complex<T> &a1,Complex<T> &a2)
{
Complex<T> temp(a1.a+a2.a,a1.b+a2.b);
return temp;
}
*/
<3>
friend Complex<T> mySub(Complex<T> &c1,Complex<T> &c2)
{
Complex<T> temp(c1.a-c2.a,c1.b-c2.b);
return temp;
}//可以实现


//friend Complex<int> mySub(Complex<int> &c1,Complex<int> &c2);
        //ostream &operator<<(ostream &out,Complex<int> &a3);
//friend Complex<int> operator+(Complex<int>&a1,Complex<int> &a2);
public:
Complex(T a,T b)
{
this->a = a;
this->b = b;
}

<2>
Complex<T> operator+(Complex<T> &a2)
{
Complex<T> temp(this->a+a2.a,this->b+a2.b);
return temp;
}//可以实现

<3>
/*Complex<T> mySub(Complex<T> &c2)
{
Complex<T> temp(this->a-c2.a,this->b-c2.b);
return temp;
}//可以实现*/
private:
T a;
T b;
};




<1>
//ostream &operator<<(ostream &out,Complex<int> &a3)
//{
// out << a3.a << "+" << a3.b << "i";
// return out;
//}//可以在外部实现


<1>
//template <typename T>
//Complex<T> mySub(Complex<T> &c1,Complex<T> &c2)
//{
// Complex<T> temp(c1.a-c2.a,c1.b-c2.b);
// return temp;
//}//在外部不能实现


<2>
//Complex<int> operator+(Complex<int> &a1,Complex<int> &a2)
//{
// Complex<int> temp(a1.a+a2.a,a1.b+a2.b);
// return temp;
//}//可以在外部实现


<2>
//template <typename T>
//Complex<T> operator+(Complex<T> &a1,Complex<T> &a2)
//{
// Complex<T> temp(a1.a+a2.a,a1.b+a2.b);
// return temp;
//}//不能在外部实现


<3>
//Complex<int> mySub(Complex<int> &c1,Complex<int> &c2)
//{
// Complex<int> temp(c1.a-c2.a,c1.b-c2.b);
// return temp;
//}//可以在外部实现


<3>
//template <typename T>
//Complex<T> mySub(Complex<T> &c1,Complex<T> &c2)
//{
// Complex<T> temp(c1.a-c2.a,c1.b-c2.b);
// return temp;
//}//不能实现








int main()
{
Complex<int> a1(1,2),a2(2,3),a3(0,0);
a3 = a1 + a2;
cout << a3 << endl;

a3 = mySub(a1,a2);
cout << a3 << endl;


return 0;
}


6.类的使用:所有的类模板函数写在类的外部
   (1)类的内部函数在外部实现


      A:类的内部成员函数在外部实现,必须全部写出函数模板
      B:类名前加T
      C:类的成员函数定义对象的时候,类型参数列表<T>,可写可不写
      D:类的返回值,一定要加上类型参数列表<T>


#include <iostream>


using namespace std;


template <typename T>
class Complex;


template <typename T>
ostream &operator<< (ostream &out,Complex<T> &a3);


template <typename T>
Complex<T> mySub(Complex<T> &c1,Complex<T> &c2);


template <typename T>
class Complex
{  
friend ostream &operator<< <T> (ostream &out,Complex &a3);
    

friend Complex<T> mySub <T> (Complex &c1,Complex &c2);


public:
Complex(T a,T b);

Complex<T> operator+(Complex<T> &a2);


private:
T a;
T b;
};


//类内部函数的外部实现
//1.类的内部成员函数在类的外部实现,必须全部写出函数模板


template <typename T>
//2.类名前加T
Complex<T>::Complex(T a,T b)
{
this->a = a;
this->b = b;
}


//3.类的成员函数定义对象的时候,类型参数列表<T>可写可不写
//4.类的返回值一定要加上类型参数列表<T>
template <typename T>


Complex<T> Complex<T>:: operator+(Complex &a2)
{
Complex temp(this->a+a2.a,this->b+a2.b);
return temp;
}






template <typename T>
Complex<T> mySub(Complex<T> &c1,Complex<T> &c2)
{
Complex<T> temp(c1.a-c2.a,c1.b-c2.b);
return temp;
}


template <typename T>
ostream &operator<< (ostream &out,Complex<T> &a3)
{
cout << a3.a << "+" << a3.b << "i";
return out;
}


int main()
{
Complex<int> a1(1,2),a2(2,3),a3(0,0);
a3 = a1 + a2;
cout << a3 << endl;

a3 = mySub<int>(a1,a2);
cout << a3 << endl;


return 0;
}


    (2)类的友元函数在外部实现
       
        A:需要在类前加 类的前置声明,函数的前置声明
B:在类的内部声明必须在函数名与参数列表直接加<T>,形参列表中可加可不加
C:友元函数外部实现,必须将参数列表中加<T>
D:友元函数外部实现,调用必须加<数据类型>


#include <iostream>


using namespace std;
//1.需要在类前加 类的前置声明,函数的前置声明
template <typename T>
class Complex;


template <typename T>
ostream &operator<< (ostream &out,Complex<T> &a3);


template <typename T>
Complex<T> mySub(Complex<T> &c1,Complex<T> &c2);


template <typename T>
class Complex
{  
        // 2.在类的内部声明必须在函数名与参数列表直接加<T>,形参列表中可加可不加
friend ostream &operator<< <T> (ostream &out,Complex &a3);
    

friend Complex<T> mySub <T> (Complex &c1,Complex &c2);


public:
Complex(T a,T b);

Complex<T> operator+(Complex<T> &a2);


private:
T a;
T b;
};






template <typename T>
Complex<T>::Complex(T a,T b)
{
this->a = a;
this->b = b;
}




template <typename T>


Complex<T> Complex<T>:: operator+(Complex &a2)
{
Complex temp(this->a+a2.a,this->b+a2.b);
return temp;
}


//友元函数的外部实现
//3.友元函数外部实现,必须将参数列表中加<T>


template <typename T>
Complex<T> mySub(Complex<T> &c1,Complex<T> &c2)
{
Complex<T> temp(c1.a-c2.a,c1.b-c2.b);
return temp;
}


template <typename T>
ostream &operator<< (ostream &out,Complex<T> &a3)
{
cout << a3.a << "+" << a3.b << "i";
return out;
}


int main()
{
Complex<int> a1(1,2),a2(2,3),a3(0,0);
a3 = a1 + a2;
cout << a3 << endl;
//4.友元函数外部实现,调用必须加<数据类型>
a3 = mySub<int>(a1,a2);
cout << a3 << endl;


return 0;
}


7.static变量在类模板中的使用
A:从类模板实例化的每个模板类有自己的类模板数据成员,该模板类的所有对象共享一个static数据成员
B:和非模板类的static数据成员一样,模板类的static数据成员也应该在文件范围定义和初始化
C:每个模板类有自己的类模板的static数据成员副本
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值