c++笔记(10):多态性(类属)、函数模板、类模板

1.

模板把函数或类要处理的数据类型参数化,表现为参数的多态性,称为类属。模板用于表达逻辑结构相同,但具体数据元素类型不同的数据对象的通用行为。

C++提供两种模板机制:函数模板和类模板
如果要求对不同数据类型的操作完全相同,用函数模板实现更为简洁方便
2.
声明模板中使用的类属参数。形式为:template  < 类型形式参数表 > 
类型形式参数的形式为:typename T1 ,  typename T2 , …… , typename Tn 或 class T1 ,  class T2 , …… , class Tn  
函数模板声明:   
template  < 类型形式参数表 >
类型  函数名 ( 形式参数表 )
{    
语句序列
}
函数模板定义由模板说明和函数定义组成
模板说明的类属参数必须在函数定义中至少出现一次
函数参数表中可以使用类属类型参数,也可以使用一般类型参数 
#include<iostream>
using namespace std;
template <typename T>//函数模板
T Max( const T a, const T b )
{ return a>b ? a : b ; }
int main()
{ cout << "Max( 3, 5 ) is " << Max( 3, 5 ) << endl ;//int  max ( int  a , int  b )程序执行时匹配不同的版本
  cout << "Max( 'y', 'e') is " << Max( 'y', 'e' ) << endl ;char  max ( char  a , char b )程序执行时匹配不同的版本
  cout << "Max( 10.3, 0.5 ) is " << Max( 10.3, 0.5 ) << endl ;double  max ( double a , double b )程序执行时匹配不同的版本
}
3.
重载函数模板:有些特殊情况需要函数模板参与重载
例如:
template < typename  T >
T  max ( T  a , T  b )
{ return  a > b ? a : b ; } 
void  f ( int  i , char  c )
{  max ( i , i ) ;		// ok
     max ( c ,  c ) ;		// ok
     max ( i ,  c ) ;		// error,无法匹配,模板类型不能提供类型的隐式转换
     max ( c ,  i ) ;		// error,模板类型不能提供类型的隐式转换
}
改为如下:
template < typename  T >
T  max ( T  a , T  b )
  { return  a > b ? a : b ; }
int  max ( int  a , char  b )	// 模板函数重载版本
  { return  a > b ? a : b ; }
void  f ( int  i , char  c )
 {  max ( i , i ) ;		// ok
     max ( c ,  c ) ;		// ok
     max ( i ,  c ) ;		// ok,调用重载函数模板
     max ( c ,  i ) ;		// ok,重载函数模板提供隐式转换 
 }
#include<iostream>//重载函数模板示例
using namespace std ;
template <typename T>
T Max( const T a, const T b )  { return a>b ? a : b ; }
template <typename T>
T Max( const T a, const T b , const T c)
{ T t ;  t = Max(a, b) ;    return Max ( t, c ) ;  }
int Max( const int a , const char b )  { return a>b ? a : b ; }

int main ( )
 { cout<< " Max( 3, 'a' ) is " << Max( 3, 'a' ) << endl ;
    cout << " Max(9.3, 0.5) is " << Max(9.3, 0.5) << endl ;
    cout << " Max(9, 5, 23) is " << Max(9, 5, 23) << endl ;
 }
寻找和使用最符合函数名和参数类型的函数,若找到则调用它;
否则,寻找一个函数模板,将其实例化产生一个匹配的模板函数,若找到则调用它;
否则,寻找可以通过类型转换进行参数匹配的重载函数,若找到则调用它
如果按以上步骤均未能找到匹配函数,则调用错误。
如果调用有多于一个的匹配选择,则调用匹配出现二义性。

4.

类模板

类模板由模板说明和类说明构成 
template    <类型形式参数表>    
  类声明
例如:
template< typename Type >
class TClass
{  // TClass的成员函数
    private :
        Type DateMember ;//类属参数必须至少在类说明中出现一次 
    //…
};
template< typename T >//一个数组类模板
class  Array
{ public :
    Array ( int s ) ;
    virtual ~ Array () ;
    virtual const T& Entry( int index ) const ;
    virtual void Enter( int index, const T & value ) ;
  protected : 
    int size ;
    T * element ;//数据成员是T类型指针
} ;
template<typename T> Array<T>::Array(int s)//类模板的成员函数是函数模板
  { if ( s > 1 ) size = s ;     else size = 1 ;
     element = new T [ size ] ;
  }
template < typename T > Array < T > :: ~Array()
  { delete [] element ; }
template < typename T > const T& Array < T > :: Entry ( int index ) const//函数返回常引用,函数调用不能做左值修改 
  { return  element [ index ] ; }
template < typename T > void Array < T > :: Enter(int index, const T& value)
  { element [ index ] = value ; }
#include<iostream>
using namespace std ;
#include "Array.h"
int main()
{ Array <int> IntAry( 5 ) ;
   int i ; 
   for ( i = 0; i < 5; i ++ )  IntAry.Enter ( i, i ) ;
   cout << "Integer Array : \n" ;
   for ( i = 0; i < 5; i ++ )  cout << IntAry.Entry(i) << '\t' ;
   cout<<endl ;
   Array <double> DouAry( 5 ) ;
   for ( i = 0; i < 5; i ++ )  DouAry.Enter ( i, (i+1)*0.35 ) ;
   cout << "Double Array : \n" ;
   for ( i = 0; i < 5; i ++ )  cout << DouAry.Entry(i) << '\t' ;
   cout<<endl;
}
类模板作函数参数:
函数的形式参数类型可以是类模板或类模板的引用,对应的实际参数是该类模板实例化的模板类对象
当一个函数拥有类模板参数时,这个函数必定是函数模板 
5.
一个类模板在类层次结构中既可以是基类也可以是派生类:
template< typename T >//从类模板Array<T>派生一个安全数组类模板BoundArray<T>
class  Array
{ public :
    Array ( int s ) ;    virtual ~ Array () ;
    virtual const T& Entry( int index ) const ;
    virtual void Enter( int index, const T & value ) ;
  protected : 
    int size ;    T * element ;
} ;
template < typename T >
class BoundArray : public Array < T >
{ public :
      BoundArray ( int low = 0, int height = 1 ) ;
      virtual  const T& Entry ( int  index ) const ;
      virtual  void Enter ( int  index , const T& value ) ;
    private: int  min ;
} ; 
类模板派生普通类,在定义派生类时要对基类的抽象类参数实例化
从普通类派生类模板,意味着派生类添加了抽象类数据成员
#include<iostream>//从类模板A派生普通类B
using namespace std ;
template< typename T >	//定义类模板
class  A
{ public :
       A( T x ) { t = x ; }
       void out() { cout << t << endl ; }
  protected : 
      T t ;
} ;
class B: public A<int>	//派生一般类
{ public :
       B ( int a,  double x ) : A <int> ( a ) { y = x ; }//实例化基类的抽象类型参数
       void out() { A <int> :: out() ;  cout << y << endl ; }
  protected :
      double y ;
};
int main()
{ A <int>  a( 123 ) ;
   a.out() ;
   B b ( 789, 5.16 ) ;
   b.out() ;
}

6.

类模板与友元

在类模板中可以声明各种友元关系,一个函数或函数模板可以是类或类模板的友元
一个类或类模板可以是类或类模板的友元.
template <typename T> class X
{ //……
     friend void f1();
}
函数f1成为类模板X实例化的每个模板类的友元函数
template <typename T> class X
{ //……
  template <typename T> friend void f2( X<T> & );
}
对特定类型(如double),使模板函数f2(X<double>&)成为X<double>的友元
template <typename T> class X
{ //……
     friend void A::f3();
}
A类的成员函数f3成为类模板X实例化的每个模板类的友元函数
template <typename T> class X
{ //……
  template <typename T> friend void B<T>::f4( X<T> & );
}
对特定类型(如double),使模板类B<double>的成员函数f4(X<double>&)成为模板类X<double>的友元
template <typename T> class X
{ //……
     friend class Y;
}
Y类的每个成员函数成为类模板X实例化的每个模板类的友元函数
template <typename T> class X
{ //……
  template <typename T> friend class Z<T>;
}
对特定类型(如double),使模板类Z<double>所有成员函数成为模板类X<double>的友元
7.
//复数类模板用定义重载运算符友元函数
#include<iostream>
using namespace std;
template<typename T>
class Complex
{ public:
     Complex( T r =0, T i =0 );
  private:  
     T  Real, Image ;	//数据成员,实部、虚部
  template<typename T> 
  friend Complex<T> operator+ ( const Complex<T> c1, const Complex<T> c2 );
  template<typename T> 
  friend Complex<T> operator- ( const Complex<T> &c1, const Complex<T> &c2 );
  template<typename T> 
  friend Complex<T> operator- ( const Complex<T> &c );
  template<typename T> 
  friend ostream & operator<< ( ostream & output, const Complex<T> & c ); 
}; 
//默认参数构造函数
template<typename T> 
Complex<T>::Complex( T r, T i )
 { Real = r ;   Image = i ;  
 } 
//重载 +
template<typename T>
Complex<T> operator+ ( const Complex<T> c1, const Complex<T> c2 )
 { T r = c1.Real + c2.Real ;   T i = c1.Image + c2.Image ;
    return Complex<T>( r, i ) ;
 }
//重载 双目 -
template<typename T> 
Complex<T> operator- ( const Complex<T> & c1, const Complex<T> & c2 )
 { T r = c1.Real - c2.Real ;   T i = c1.Image - c2.Image ;
   return Complex<T>( r, i ) ;
 }
//重载 单目 -
template<typename T>
Complex<T> operator- ( const Complex<T> & c )
 { return Complex<T> ( -c.Real, -c.Image ); 
 }
//重载 <<
template<typename T> 
ostream & operator<< ( ostream & output, const Complex<T> & c )
{ output << '(' << c.Real << " , " << c.Image << ')' ;
  return output;
} 
int main()
 { Complex<double> c1( 2.5,3.7 ), c2( 4.2, 6.5 ) ;
    cout << "c1 = "<< c1 << "\nc2 = " << c2 << endl;
    cout << "c1 + c2 = " << c1+c2 << endl ;
    cout << "c1 - c2 = " << c1-c2 << endl ;
    cout << "-c1 = " << -c1 << endl ;
 } 

8.

类模板与static成员

从类模板实例化的每个模板类有自己的类模板数据成员,该模板类的所有对象共享一个static数据成员
和非模板类的static数据成员一样,模板类的static数据成员也应该在文件范围定义和初始化
每个模板类有自己的类模板的static数据成员副本
#include<iostream>//为圆类模板定义静态成员
using namespace std ;
const double pi=3.14159;
template<typename T> class Circle
{   T radius ; 
     static int total;			//类模板的静态数据成员
  public :
     Circle(T r=0) { radius = r ; total++; }
     void Set_Radius( T r ) { radius = r ; }
     double Get_Radius()   { return  radius ; }
     double Get_Girth()      { return  2 * pi * radius ; }
     double Get_Area()       { return  pi * radius * radius ; }
     static int ShowTotal();		//类模板的静态成员函数
} ;
template<typename T> int Circle<T>::total=0;
template<typename T> 
int Circle<T>::ShowTotal(){ return total; } 
int main()
{  Circle<int> A, B ;		//建立了2个对象
   A.Set_Radius( 16 ) ;
   cout << "A.Radius = " << A.Get_Radius() << endl ;
   cout << "A.Girth = " << A.Get_Girth() << endl ;
   cout << "A.Area = " << A.Get_Area() << endl ;
   B.Set_Radius( 105 ) ;
   cout << "B.radius = " << B.Get_Radius() << endl ;
   cout << "B.Girth=" << B.Get_Girth() << endl ;
   cout << "B.Area = " << B.Get_Area() << endl ; 
   cout<<"Total1="<<Circle<int>::ShowTotal()<<endl;	//显示建立的对象数
   cout<<endl;
   Circle<double> X(6.23), Y(10.5), Z(25.6);		//建立了3个对象
   cout << "X.Radius = " << X.Get_Radius() << endl ;
   cout << "X.Girth = " << X.Get_Girth() << endl ;
   cout << "X.Area = " << X.Get_Area() << endl ;
   cout << "Y.radius = " << Y.Get_Radius() << endl ;
   cout << "Y.Girth=" << Y.Get_Girth() << endl ;
   cout << "Y.Area = " << Y.Get_Area() << endl ; 
   cout << "Z.Girth=" << Z.Get_Girth() << endl ;
   cout << "Z.Area = " << Z.Get_Area() << endl ; 
   cout<<"Total2="<<Circle<double>::ShowTotal()<<endl;	//显示建立的对象数
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值