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,十分感谢
           

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值