函数重载·函数模板·类模板

本文深入讲解C++中的函数重载、函数模板和类模板的概念及其使用方法,通过具体示例帮助理解不同模板的应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一 函数重载

    C++允许功能相近的函数在相同的作用域内以相同的函数名声明,从而形成重载。方便使用,便于记忆。
例:
参数类形不同:
int add(int x,int y);
float add(float x,float y);
参数个数不同:
int add(int x,int y);
int add(int x,int y,int z);

注意:
重载函数的形参必须不同:个数不同或类型不同。
编译程序将根据实参和形参的类型及个数的最佳匹配来选择调用哪个函数。
int add(int x,int y);
int add(int a,int b);
编译器不以形参名来区分
int add(int x,inty);
void add(int x,inty);
编译器不以返回值来区分
不要将不同功能的函数声明为重载函数,以免出现调用结果的误触,混淆。这样不好:
int add(int x,int y) {return x+y;}
float add(float x,float y) {return x-y;}

例:编写三个名为add的重载函数,分别实现两整数相加,两实数相加和两个重复数相加的功能。

#include<iostream.h>
struct complex
{
double real;
double imag;
}

int add(int m,int n) {return m+n;}
double add(double x,double y) {return x+y;}
complex add(complex c1,complex c2) {
complex c;
c.real=c1.real+c2.real;
c.imag=c1.imag+c2.imag;
return c;
}
void main(void)
{
int m,n;
double x,y;
complex c1, c2, c3;
int add(int m,int n);
double add(double x,double y);
complex add(complex c1,complex c2);

cout<<"Enter two integer:";
cin>>m>>n;
cout<<"integer"<<m<<'+'<<n<<"="<<add(m,n)>>endl;
cout<<"Enter two real number:";
cin>>x>>y;
cout<<"real number"<<x<<'+'<<y<<"="<<add(x,y)<<endl;
cout<<"Enter the first complex number:";
cin>>c1.real>>c1.imag;
cout<<"Enter the second complex number:";
cin>>c2.real>>c2.imag;
c3=add(c1,c2);
cout>>"complex number("<<c1.real<<','<<c1.imag<<")+("<<c2.real<<','<<c2.imag<<")=(<<c3.real<<','<<c3.imag<<")/n";
}

二函数模板
  函数模板可以用来创建一个通用功能的函数,以支持多种不同形参,进一步简化重载函数的函数体设计。

声明方法:
template<typename 标识符>
函数声明

例:
#inclue<iostream.h>

template<typename T>
T abs(T x)
{ return x<0?-x:x; }

void main()
{
int n=-5;
double d=-5.5;
cout<<abs(n)<<endl;
cout<<abs(d)<<endl;
}

分析:
编译器从调用abs()时实参的类型,推导出函数模板的类型参数。例如,对于调用表达式abs(n),由于实参n为int型,所以推导出模板中类型参数T为int.

当类型参数的含义确定后,编译器将以函数模板为样板,生成一个函数:
int abs(int x)
{ return x<0?-x:x; }

三类模板
使用类模板使用户可以为类声明一种模式,使得类中的某些数据成员,某些成员函数的参数,某些成员函数的返回值,能取任意类型(凶手系统定义的和用户自定义的)。

template<模板参数表》
类声明

定义一个类模板与定义函数模板的格式类似,必须以关键字template开始,后面是尖括号括起来的模板参数,然后是类名,其格式如下:
template<class Type>
class类名{
···
···
};
其中template是一个声明模板的关键字,它表示声明一个模板。关键字class表明后面的Type是模板参数。

例:
#include<iostream.h>
#include<math.h>
template<class T>
class complex
{
private:
T real;
T imag;
public:
complex(T r=0.0,T i=0.0) { real=r; imag=i;}
T realcomplex() { return real;}
T imagcomplex() { return imag;}
T abscomplex() { double t;  t=(double)real*real+(double)imag*imag; return sqrt(t); }

注意:
在类定义体外定义成员函数时,若此成员函数中有模板参数存在,则需要在函数体外进行模板声明,并且在函数名前的类名后缀上"<Type>"
例如,成员函数在类外定义为:
template<class T>
T complex<T>::reakcomplex() 
{ return real; }

类模板不代表一个具体的,实际的上,类模板的使用就是将类模板实例化成一个具体的类,它的格式为:
类名《实际的类型》对象名;
例如,使用上面的类模板,创建两个模板参数为double型的对象,语句如下:
complex<double>s1,s2;
创建两个模板参数为int型的对象,语句如下:
complex<int>s1,s2;
1.类模板与模板类的概念
⑴ 什么是类模板 一个类模板(也称为类属类或类生成类)允许用户为类定义一种模式,使得类中的某些数据成员、默写成员函数的参数、某些成员函数的返回值,能够取任意类型(包括系统预定义的和用户自定义的)。
  如果一个类中数据成员的数据类型不能确定,或者是某个成员函数的参数或返回值的类型不能确定,就必须将此类声明为模板,它的存在不是代表一个具体的、实际的类,而是代表着一类类。
⑵ 类模板定义 定义一个类模板,一般有两方面的内容:
A.       首先要定义类,其格式为:
template <class T>
class foo
{
……
}
foo 为类名,在类定义体中,如采用通用数据类型的成员,函数参数的前面需加上T,其中通用类型T可以作为普通成员变量的类型,还可以作为const和static成员变量以及成员函数的参数和返回类型之用。例如:
template<class T>
class Test{
private:
    T n;
    const T i;
    static T cnt;
public:
    Test():i(0){}
    Test(T k);
    ~Test(){}
    void print();
    T operator+(T x);
};
B.       在类定义体外定义成员函数时,若此成员函数中有模板参数存在,则除了需要和一般类的体外定义成员函数一样的定义外,还需在函数体外进行模板声明
例如
template<class T>
void Test<T>::print(){
    std::cout<<"n="<<n<<std::endl;
    std::cout<<"i="<<i<<std::endl;
    std::cout<<"cnt="<<cnt<<std::endl;
 
}
如果函数是以通用类型为返回类型,则要在函数名前的类名后缀上“<T>”。例如:
template<class T>
Test<T>::Test(T k):i(k){n=k;cnt++;}
template<class T>
T Test<T>::operator+(T x){
               return n + x;
               }
C.       在类定义体外初始化const成员和static成员变量的做法和普通类体外初始化const成员和static成员变量的做法基本上是一样的,唯一的区别是需在对模板进行声明,例如
template<class T>
int Test<T>::cnt=0;
template<class T>
Test<T>::Test(T k):i(k){n=k;cnt++;}
⑶ 类模板的使用 类模板的使用实际上是将类模板实例化成一个具体的类,它的格式为:类名<实际的类型>。
  模板类是类模板实例化后的一个产物。说个形象点的例子吧。我把类模板比作一个做饼干同的模子,而模板类就是用这个模子做出来的饼干,至于这个饼干是什么味道的就要看你自己在实例化时用的是什么材料了,你可以做巧克力饼干,也可以做豆沙饼干,这些饼干的除了材料不一样外,其他的东西都是一样的了。
2.类模板的派生
  可以从类模板派生出新的类,既可以派生类模板,也可以派生非模板类。派生方法:
⑴ 从类模板派生类模板可以从类模板派生出新的类模板,它的派生格式如下例所示:
template <class T>
class base
{
……
};
 
template <class T>
class derive:public base<T>
{
……
};
与一般的类派生定义相似,只是在指出它的基类时要缀上模板参数,即base<T>。
⑵ 从类模板派生非模板类  可以从类模板派生出非模板类,在派生中,作为非模板类的基类,必须是类模板实例化后的模板类,并且在定义派生类前不需要模板声明语句:template<class>。例如:
template <class T>
class base
{
……
};
 
class derive:public base<int>
{
……
};
在定义derive类时,base已实例化成了int型的模板类

本文来自优快云博客,转载请标明出处: http://blog.youkuaiyun.com/justin12zhu/archive/2009/02/15/3893422.aspx
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值