-
重载函数(overload function)
-
在C语言中,不允许函数有同名函数,C++通过重载函数名来避免这类麻烦。你可以在同一个程序里使用同名的两个或多个函数。函数名重载可以让函数使用起来更“自然”。使用了重载的程序也更容易读和写。
-
C++中声明重载的函数跟声明其它函数没什么不同。只不过它跟其它的某个函数重名。重载函数必须使用不同的变量,否则编译器没法区分它们。
-
编译器无法通过函数不同的返回类型来区别重载函数
-
当编译器遇到对函数put的调用,它会选择函数参数完全匹配的函数声明进行调用。这个过程叫做重载决策
-
有可能会有多个重载函数能够匹配一个函数调用。
-
当面对多个可选函数时,重载决策根据函数参数类型的隐式转换来排序,找出最匹配的那个。
-
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)并为被声明,那么二三的优先序相同。当重载决策没有办法选出一个最优匹配,那么调用就是不明确的,这会产生一个编译错误
-
-
模板(template)
- 模板有模板函数和模板类,定义方式如下:
定义: template <class identifier> function() {/函数主体/}; template <typename identifier> function() {/函数主体/}; 声明: template <class identifier> function(); template <typename identifier> function();
模板的实例化是编译器做的事情,与程序员无关
-
类模板的使用
-
//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)。
-
类模板对象的创建:比如一个模板类A,则使用类模板创建对象的方法为A<int> m;在类A后面跟上一个<>尖括号并在里面填上相应的类型,这样的话类A中凡是用到模板形参的地方都会被int 所代替。当类模板有两个模板形参时创建对象的方法为A<int, double> m;类型之间用逗号隔开。
-
模板的声明或定义只能在全局,命名空间或类范围内进行。即不能在局部范围,函数内进行,比如不能在main函数中声明或定义一个模板。
-
模板的形参(三种类型的模板形参:类型形参,非类型形参和模板形参)
-
类型模板形参:类型形参由关见字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,此时就不会有上述的警告,因为从int到double是自动类型转换
-
-
模板的特例化
-
-
非类型形参
-
非类型模板形参:模板的非类型形参也就是内置类型形参,如template<class T, int a> class B{};其中int a就是非类型的模板形参。
-
非类型形参在模板定义的内部是常量值,也就是说非类型形参在模板的内部是常量。
-
非类型模板的形参只能是整型,指针和引用,像double,String, String **这样的类型是不允许的。但是double &,double *,对象的引用或指针是正确的。
-
调用非类型模板形参的实参必须是一个常量表达式,即他必须能在编译时计算出结果。
-
注意:任何局部对象,局部变量,局部对象的地址,局部变量的地址都不是一个常量表达式,都不能用作非类型模板形参的实参。全局指针类型,全局变量,全局对象也不是一个常量表达式,不能用作非类型模板形参的实参。
-
全局变量的地址或引用,全局对象的地址或引用const类型变量是常量表达式,可以用作非类型模板形参的实参。
-
、sizeof表达式的结果是一个常量表达式,也能用作非类型模板形参的实参。
-
当模板的形参是整型时调用该模板时的实参必须是整型的,且在编译期间是常量,比如template <class T, int a> class A{};如果有int b,这时A<int, b> m;将出错,因为b不是常量,如果const int b,这时A<int, b> m;就是正确的,因为这时b是常量。
-
非类型形参一般不应用于函数模板中,比如有函数模板template<class T, int a> void h(T b){},若使用h(2)调用会出现无法为非类型形参a推演出参数的错误,对这种模板函数可以用显示模板实参来解决,如用h<int, 3>(2)这样就把非类型形参a设置为整数3。显示模板实参在后面介绍。
-
非类型模板形参的形参和实参间所允许的转换
-
允许从数组到指针,从函数到指针的转换。如:template <int *a> class A{}; int b[1]; A<b> m;即数组到指针的转换
-
const修饰符的转换。如:template<const int *a> class A{}; int b; A<&b> m; 即从int *到const int *的转换。
-
提升转换。如:template<int a> class A{}; const short b=2; A<b> m; 即从short到int 的提升转换
-
整值转换。如:template<unsigned int a> class A{}; A<3> m; 即从int 到unsigned int的转换。
-
常规转换
-
-
- 使用类模板时要注意其作用域,只能在其有效作用域内用它定义对象。
- 本文较大部分引用自https://blog.csdn.net/biu__biu_biu/article/details/78020620,十分感谢
-
-
- 模板有模板函数和模板类,定义方式如下: