c++的三大特性

Operator Overloading

下面的代码是一段运算符重载代码:

  1. class CVeryLong 
  2.   {
  3.   public:
  4.       // default contructor inits member variables to zero
  5.       CVeryLong(){ m_lHigh = m_lLow = 0; } 
  6.       // initialization constructor sets member variables to a value
  7.       CVeryLong( long lHigh, long lLow ){ m_lHigh = lHigh; m_lLow = lLow; } 
  8.       virtual ~CVeryLong(){}; // destructor
  9.       void SetHighValue( long lValue ){ m_lHigh = lValue; }
  10.       long GetHighValue(){ return m_lHigh; }
  11.       void SetLowValue( long lValue ){ m_lLow = lValue; }
  12.       long GetLowValue(){ return m_lLow; }
  13.       BOOL operator < ( CVeryLong& refValue )    // less than operator
  14.       {
  15.           if ( m_lHigh < refValue.GetHighValue()) return TRUE;
  16.           else if ( m_lHigh > refValue.GetHighValue()) return FALSE;
  17.           else if ( m_lLow < refValue.GetLowValue()) return TRUE;
  18.           else return FALSE; // >=
  19.       }
  20.       BOOL operator > ( CVeryLong& refValue )    // greater than operator
  21.       {
  22.           if ( m_lHigh > refValue.GetHighValue()) return TRUE;
  23.           else if ( m_lHigh < refValue.GetHighValue()) return FALSE;
  24.           else if ( m_lLow > refValue.GetLowValue()) return TRUE;
  25.           else return FALSE; // <=
  26.       }
  27.       BOOL operator == ( CVeryLong& refValue ) // equivalence operator
  28.       {
  29.           return m_lHigh == refValue.GetHighValue() 
  30.                    && m_lLow == refValue.GetLowValue();
  31.       }
  32.   private:
  33.       long m_lLow;
  34.       long m_lHigh;
  35.   };

CVeryLong 类有两个long私有变量,能够显示一个64位整型数。在这个类中,我们重载了小于号(<),大于号(>),等于号(=),使得64位整数类可以进行比较运算。显然,这个类是不完整的,因为还有很多数学运算符没重载。下面的代码简单使用我们的新类:

  1. {
  2.    CString csText;
  3.    CVeryLong vl1( 1, 2 ), vl2( 1, 3 ), vl3;
  4.    
  5.    cout << "vl1 is (1, 2)" << endl;
  6.    cout << "vl2 is (1, 3)" << endl;
  7.    cout << "vl3 is (1, 2)" << endl;
  8.        
  9.    csText = "vl1 < vl2 is ";
  10.    csText += vl1 < vl2 ? "true" : "false";
  11.    cout << (LPCTSTR)csText << endl;
  12.    csText = "vl1 > vl2 is ";
  13.    csText += vl1 > vl2 ? "true" : "false";
  14.    cout << (LPCTSTR)csText << endl;
  15.    csText = "vl1 = = vl2 is ";
  16.    csText += vl1 == vl2 ? "true" : "false";
  17.    cout << (LPCTSTR)csText << endl;
  18.    csText = "vl1 < vl3 is ";
  19.    csText += vl1 < vl3 ? "true" : "false";
  20.    cout << (LPCTSTR)csText << endl;
  21.    csText = "vl1 > vl3 is ";
  22.    csText += vl1 > vl3 ? "true" : "false";
  23.    cout << (LPCTSTR)csText << endl;
  24.    csText = "vl1 = = vl3 is ";
  25.    csText += vl1 == vl3 ? "true" : "false";
  26.    cout << (LPCTSTR)csText << endl;
  27. }

 

运行结果:

  1.        vl1 is (1, 2)
  2.        vl2 is (1, 3)
  3.        vl3 is (1, 2)
  4.        vl1 < vl2 is true
  5.        vl1 > vl2 is false
  6.        vl1 == vl2 is false
  7.        vl1 < vl3 is false
  8.        vl1 > vl3 is false
  9.        vl1 == vl3 is true

在这里,我们告诉编译器当它看到<,>,或=作用在我们的新类中该做什么,在别的语言中可以定义成员函数来做同样的事。

Exceptions

异常需要有语言的支持,否则将很难被复制。Windows NT 提供Structured Exception Handing(SEH)的复杂功能,这种由操作系统提供的功能和C++提供的异常是同一种类型。其他语言可以获得SEH带来的好处,而C++的轻便机制使得它能够在所有的操作系统中工作的像SEH一样好。

异常处理正如名字所暗示:有处理异常情况的能力,不会增加正常情况的负担。下面的代码是异常处理。

  1. DWORD dwStart = ::GetTickCount(); // used for timing in mSec
  2. const int x = 1000000;
  3. const int xEnd = -x;
  4. int y = x;
  5. int z;
  6. while ( y > xEnd )
  7. {
  8.     try
  9.     {
  10.         while ( y > xEnd )
  11.             z = x / y--; // divide protected by exception
  12.     }
  13.     catch (...)
  14.     {
  15.         cout << "Divide by zero" << endl; // trapped out of inner loop
  16.         y--; // continue via outer loop
  17.     }
  18. }
  19. DWORD dwStop = ::GetTickCount();
  20. DWORD dwDiff = dwStop - dwStart;
  21. CString csMessage;
  22. csMessage.Format( "mSec = %d", dwDiff );
  23. cout << (LPCTSTR)csMessage << endl;

输出:

Divide by zero
mSec = 491
内层循环不需要检查是否除0,当发生除0时,把它当成一个异常来处理了。对比没有异常时上面的代码应该写成:
  
  
  1. while ( y > xEnd )
  2. {    
  3.     if ( x != 0 ) // has to execute for every iteration
  4.     {
  5.         z = x / y--;
  6.     }
  7.     else
  8.     {
  9.         cout << "Attempted divide by zero" << endl;
  10.     }
  11. }

Templates

Function Templates

通过函数模板,可以指定一类函数基于相同的代码,但是不同的类型或是类却有不同的功能。下面是一个模板函数,
返回两个数中的最大值。
  
  
  1. template <class T> T& Max( T& a, T& b ) 
  2. {
  3.     if ( a >  b ) return a; else return b;
  4. }
通过这种方式,可以避免 MaxFloat, MaxInt, MaxShort, MaxChar等函数的实现。如果调用Max时,使用float,
编译器将会进行编译。由于可以重载运算符,Max函数就不在局限于基本类型。上面的CVeryLong类也能够适用。

Class Templates

     
     
  1. template<class KEY, class ARG_KEY, class DATA, class ARG_DATA>
  2. class CTree 
  3. {
  4. private:
  5.     typedef enum
  6.     {   balLeft = -1,
  7.         balEven,
  8.         balRight,
  9.     } BALANCE;
  10.     class CNode;
  11.     typedef CNode* PNODE;
  12.     class CNode // container to hold the data and hide the balancing details
  13.     {
  14.     public:
  15.         CNode( ARG_KEY key, ARG_DATA data );
  16.         // additional members not shown
  17.     private:
  18.         KEY m_key;
  19.         DATA m_data;
  20.         BALANCE m_Bal; // -1..1 current balance data for this node
  21.         PNODE m_pLeft;
  22.         PNODE m_pRight;
  23.     };
  24.     CTree(){ m_pRoot = 0; m_nSize = 0; m_bHeightChange = false; }
  25.     virtual ~CTree();
  26.     bool GetFirst( ARG_KEY key, ARG_DATA data );
  27.     bool GetLast( ARG_KEY key, ARG_DATA data );
  28.     bool GetNext( ARG_KEY key, ARG_DATA data );
  29.     bool GetPrev( ARG_KEY key, ARG_DATA data );
  30.     bool Add( ARG_KEY key, ARG_DATA data );
  31.     ARG_DATA operator[]( ARG_KEY key );
  32.     bool Delete( ARG_KEY key );
  33.     // additional members not shown
  34. private:
  35.     CNode* m_pRoot;
  36.     bool m_bHeightChange;
  37.     int m_nSize;
  38. };

上面的类通过指定不同类型,将产生新的类,这些类所具有的操作是相同的。

让我们来看下,模板的声明:

template<class KEY, class ARG_KEY, class DATA, class ARG_DATA>
class CTree
在声明中有四个参数,指定键的类型,键的传递方式,数据类型,数据的传递方式
CTree<CString, const char*, CVeryLong,CVeryLong&> treeVeryLong;
CTree<CString, const char*, float,float> treeFloat; 
CTree<long, long, CString, constchar*> treeString; 
CTree<CVeryLong,   CVeryLong,CList<int, int>, <int,int>&> treeList;
第一个例子是一棵以CVeryLong为数据,CString为键的树,键的传递方式是 const char* ,数据的传递
方式是通过引用。
类模板提供了强大的代码重用机制。
 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值