C++ essential(Day 2)(重載函數和模板)

  1. 重載函數(overload function)

    1. 在C語言中,不允許函數有同名函數,C++通過重載函數名來避免這類麻煩。你可以在同一個程序裏使用同名的兩個或多個函數。函數名重載可以讓函數使用起來更“自然”。使用了重載的程序也更容易讀和寫。

    2. C++中聲明重載的函數跟聲明其它函數沒什麼不同。只不過它跟其它的某個函數重名。重載函數必須使用不同的變量,否則編譯器沒法區分它們。

    3. 編譯器無法通過函數不同的返回類型來區別重載函數

    4. 當編譯器遇到對函數put的調用,它會選擇函數參數完全匹配的函數聲明進行調用。這個過程叫做重載決策

    5. 有可能會有多個重載函數能夠匹配一個函數調用。

    6. 當面對多個可選函數時,重載決策根據函數參數類型的隱式轉換來排序,找出最匹配的那個。

    7. void f(int i);
      void f(long int li);
      void f(char *p);
      void f(double d, int i);

      對如上的程序,如果輸入int k=f(0);第一二三均符合規範,但第二三個需要強制轉換格式,所以選擇第一個。假設      void f(int)併爲被聲明,那麼二三的優先序相同。當重載決策沒有辦法選出一個最優匹配,那麼調用就是不明確的,這會產生一個編譯錯誤

  2. 模板(template)

    1. 模板有模板函數和模板類,定義方式如下:
      定義:
      template <class identifier> 
      function()
      {/函數主體/};
      template <typename identifier> 
      function()
      {/函數主體/};
      聲明:
      template <class identifier> function();
      template <typename identifier> function();

      模板的實例化是編譯器做的事情,與程序員無關

    2. 類模板的使用

      1. //statck.h
        template <class T> class Stack {
            public:
                Stack();
                ~Stack();
                void push(T t);
                T pop();
                bool isEmpty();
            private:
                T *m_pT;        
                int m_maxSize;
                int m_size;
        };
        
        #include "stack.cpp"
        //stack.cpp
        template <class  T>  Stack<T>::Stack(){
           m_maxSize = 100;      
           m_size = 0;
           m_pT = new T[m_maxSize];
        }
        template <class T>  Stack<T>::~Stack() {
           delete [] m_pT ;
        }
                
        template <class T> void Stack<T>::push(T t) {
            m_size++;
            m_pT[m_size - 1] = t;
            
        }
        template <class T> T Stack<T>::pop() {
            T t = m_pT[m_size - 1];
            m_size--;
            return t;
        }
        template <class T> bool Stack<T>::isEmpty() {
            return m_size == 0;
        }

        注意:對於函數模板而言不存在 h(int,int) 這樣的調用,不能在函數調用的參數中指定模板形參的類型,對函數模板的調用應使用實參推演來進行,即只能進行 h(2,3) 這樣的調用,或者int a, b; h(a,b)

      2. 類模板對象的創建:比如一個模板類A,則使用類模板創建對象的方法爲A<int> m;在類A後面跟上一個<>尖括號並在裏面填上相應的類型,這樣的話類A中凡是用到模板形參的地方都會被int 所代替。當類模板有兩個模板形參時創建對象的方法爲A<int, double> m;類型之間用逗號隔開。

      3. 模板的聲明或定義只能在全局命名空間或類範圍內進行。即不能在局部範圍,函數內進行,比如不能在main函數中聲明或定義一個模板。

      4. 模板的形參(三種類型的模板形參:類型形參,非類型形參和模板形參

        1. 類型模板形參:類型形參由關見字class或typename後接說明符構成,如template<class T> void h(T a){};其中T就是一個類型形參,類型形參的名字由用戶自已確定。模板形參表示的是一個未知的類型。模板類型形參可作爲類型說明符用在模板中的任何地方,與內置類型說明符或類類型說明符的使用方式完全相同,即可以用於指定返回類型,變量聲明等。

          針對函數模板 不能爲同一個模板類型形參指定兩種不同的類型,比如 template<typename T>void h(T a, T b){},語句調用h(2, 3.2)將出錯,因爲該語句給同一模板形參T指定了兩種類型,第一個實參2把模板形參T指定爲int,而第二個實參3.2把模板形參指定爲double,兩種類型的形參不一致,會出錯。

          針對於類模板:當我們聲明類對象爲:A<int> a,比如template<class T>T g(T a, T b){},語句調用a.g(2, 3.2)在編譯時不會出錯,但會有警告,因爲在聲明類對象的時候已經將T轉換爲int類型,而第二個實參3.2把模板形參指定爲double,在運行時,會對3.2進行強制類型轉換爲3。當我們聲明類的對象爲:A<double> a,此時就不會有上述的警告,因爲從intdouble是自動類型轉換

      5. 模板的特例化

        1. 非類型形參

          1. 非類型模板形參:模板的非類型形參也就是內置類型形參,如template<class T, int a> class B{};其中int a就是非類型的模板形參。

          2.  非類型形參在模板定義的內部是常量值,也就是說非類型形參在模板的內部是常量。

          3. 非類型模板的形參只能是整型,指針和引用,像double,String, String **這樣的類型是不允許的。但是double &,double *,對象的引用或指針是正確的。

          4.  調用非類型模板形參的實參必須是一個常量表達式,即他必須能在編譯時計算出結果。

          5. 注意:任何局部對象,局部變量,局部對象的地址,局部變量的地址都不是一個常量表達式,都不能用作非類型模板形參的實參。全局指針類型,全局變量,全局對象也不是一個常量表達式,不能用作非類型模板形參的實參。

          6.  全局變量的地址或引用,全局對象的地址或引用const類型變量是常量表達式,可以用作非類型模板形參的實參

          7. sizeof表達式的結果是一個常量表達式,也能用作非類型模板形參的實參。

          8. 當模板的形參是整型時調用該模板時的實參必須是整型的,且在編譯期間是常量,比如template <class T, int a> class A{};如果有int b,這時A<int, b> m;將出錯,因爲b不是常量,如果const int b,這時A<int, b> m;就是正確的,因爲這時b是常量。

          9. 非類型形參一般不應用於函數模板中,比如有函數模板template<class T, int a> void h(T b){},若使用h(2)調用會出現無法爲非類型形參a推演出參數的錯誤,對這種模板函數可以用顯示模板實參來解決,如用h<int, 3>(2)這樣就把非類型形參a設置爲整數3。顯示模板實參在後面介紹。

          10. 非類型模板形參的形參和實參間所允許的轉換

            1. 允許從數組到指針,從函數到指針的轉換。如:template <int *a> class A{}; int b[1]; A<b> m;即數組到指針的轉換

            2. const修飾符的轉換。如:template<const int *a> class A{}; int b; A<&b> m;   即從int *到const int *的轉換。

            3. 提升轉換。如:template<int a> class A{}; const short b=2; A<b> m; 即從short到int 的提升轉換

            4. 整值轉換。如:template<unsigned int a> class A{};   A<3> m; 即從int 到unsigned int的轉換。

            5. 常規轉換​​​​​​​​​​​​​​​​​​​​​​​​​​​​

        2. ​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​使用類模板時要注意其作用域,只能在其有效作用域內用它定義對象。
        3. 本文較大部分引用自https://blog.csdn.net/biu__biu_biu/article/details/78020620,十分感謝
           

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章