c++初学者必看 学习的好东西

//函数指针不能用标准转换成void*.
typedef int (*PFV)();
extern PFV testCases[10];//函数指针数组
extern void reset(void*);
int main(){
//...
reset(testCases[0]);//错误,int(*)()
//之间不存在标准转换
return 0;
}


//函数重载解析细节
//候选函数:
void f();
void f(int );
void f(double ,double = 3.4);
void f(double char*, char*);   //四个在调用点上可见。
int main(){
f(5.6);//这个调用有四个候选函数
return 0;
}

namespace NS{
class c{/*...*/};
void takec(c&);
}
//cobj的类型是在名字空间NS中被声明的类C
NS::c  cobj;
int main(){   //在调用点没有tacec()可见
tacec(cobj);//ok:调用NS::takec(c&)
                    //因为实以类型是NS::c
                   //所以考虑在名字空间NS中声明的函数takec()
return 0;
}
//在实参类型所在的名字空间中声明的同名函数也是候选函数。

char *format(int );             //全局域声明函数被隐藏,
void g(){       //在调用点上不可见。   
char *format(double );
char *format (char *);
format (3);//调用format(double)
}
                   
namespace libs_R_us{
int max (int ,int );
double max (double , double );
}
char max (char ,char);
void func()
{
  //名字空间的函数不可见
//调用全局函数三次
max(87,65);
max (35.5,76.6);
max('j','l');
}
//用using声明使名字空间函数可见。

//若有char max (char,char);
using libs_R_us::max;//using 声明,在调用点可见。
          //分别调用三个max函数

void func()
{
  //using 声明,全局域中max(char, char)被隐藏。
using libs_R_us::max;
//函数调用如上
}

//在全局域中使用using 指示符
char max (char ,char );
using namespace libs_R_us;//using 指示符
//使三个max都可见
//若
void func()
{
 //using 指示符
using namespace libs_R_us;
//函数调用如上
}
//三个max 都可见
 //记住:using指示符使名字空间成员可见,就好像它们是
//在名字空间外,在定义名字空间的位置上被声明的一样

//缺省实参
extern void ff(int );
extern void ff(long, int =0);
int main(){
ff(2L);//匹配ff(ling, 0);
ff(0,0);//匹配ff(long, int);
ff(0);//   ff(int);
ff(3.14);//错误,二义性。

//函数模板的定义
template<class Type>
Type min(Type a,Type b){
return a<b?a:b;
}
int main(){
//ok:int min(int,int);
min(10,20);
//ok:double min(souble, double);
min(10.0,20.0);
return 0;
}


template<class Type,int size>
Type min(const Type(&r_array)[size])
{
 /*找到数组中元素最小值的参数化函数*/
 Type min_val = r_array[0];
 for(int i = 1;i<size;++i)
   if(r_array[i]<min_val)
     min_val = r_array[i];
return min_val;
}


typedef double Type;
template<class Type>
  Type min(Type a, Type b)
 {
   //tmp类型为模板参数 type
   //不是全局typedef
Type tmp = a<b?a:b;
 return tmp;
}
//全局域中声明了与模板参数同名的对象,或类型,
//则该全局名将被隐藏。

template<class Type>
Type min(Type a, Type b)
{
  //错误:重新声明模板参数Type
  typedef double Type;
  Type tmp = a<b?a:b;
   return tmp;
}
//函数模板定义中声明的对象或类型不能与模板参数同名。

//ok:T1表示min()的返回类型
//T2和T3表示参数类型
template<class T1,class T2,class T3>
  T1 min(T2,T3);
//模板类型参数名可以被用来指定函数模板的返回值。


//错误:模板参数名Type的非法重复使用。
template<class Type,class Type>
Type min(Type,Type);
//参数表中,同一模板参数只能被使用一次!


//ok:关键字typename和class 可以混用
template<typename T,class U>
T minus(T*,U);

//错误:必须是<typename T,class U>或
//<typename T,typename U>
template<typename T,U>
  T sum(T*,U);


template<class parm, class U>
 parm minus (parm* array, U value>
{
  parm::name *p;  //这是一个指针声明还是乘法?
 }
//parm是一个类
//修改如下:
tempate<class parm,class U>
 parm minus (parm*array, U value)
 {
   typename parm::name *p;//ok:指针声明
}
//typename告诉编译器是类型表达式


//ok: 关键字声明为inline,放在参数表后面
template<typename Type>
inline                                 //inline或extern
 Type min(Type,Type);
 
//错误:inline指示符没有放在参数表后面
inline
template<typename Type>
Type min(Array<Type>,int);

template<typename Type,int size>
Type min(Type<&r_array)[size])
{Type min_val = r_array[0];
 for(int i = 1;i<size;++i)
  if(r_array[i]<min_val)
    min_val = r_array[i];
     return min_val;
}
//size没有被指定——ok
//size = 初始化表中的值的个数
int ia[] = {10,7,14,3,25};
double da[6] = {10.2,7.1,14.5,3.2,25.0,16.8};

#incluce<iostream>
int main()
{
  //为5个int 的数组实例化min()
int i = min (ia);
if( i != 3 )
   cout<<"??oops:integer min() failed/n";
    else cout<<"!!ok:integer min() worked/n";
//为6个double 的数组实例化min()
double d = min ( da );
if ( d != 3.2 )
   cout << "??oops:double min() failed/n";
 else cout<< " !!ok:double min() worked/n ";
 return 0;
}
 
template<typename Type,int size>
 Type min(Type(&p_array)[size]){/*...*/}
//pf指向int min(int(&)[10])
int (*pf)(int(&)[10]) = &min;
//pf的类型是指向函数的指针
//函数模板在它被调用或取其地址时被实例化。

template<typename Type,int size>
 Type min(Type(&r_array)[size]){/*...*/}
typedef int(&rai)[10];
typedef double(&rad)[20];
void func(int(*)(rai));
void func(double (*)(rad);
int main(){
//错误:哪一个min()的实例?
func(&min);
}

//取函数模板实例的地址时,必须为模板实参决定一个唯一的类型或值。
//因为函数func()被重载了,不能为模板参数决定唯一的类型和值。
//调用func()无法实例化下面的任何一个函数。
min(int(*)(int(&)[10]))
min(double(*)(double(&)[20]))
int main(){
//ok:强制转换指定实参类型
func(static_cast<double(*)(rad)>(&min));}


//模板实参推演
template<class Type,int size>
Type min(Type(&r_array)[size]){/*...*/}
//min()函数是一个引用,它指向了一个Type类型的数组;
void f(int pval[q]){
//错误:Type(&)[]!=int*
int ival = min(pval);
}
//为了匹配函数参数,函数实参必须也是一个表示数组类型的左值。

double da[8] = {10.3,7.2;14.0,3.8,25.7,6.4,5.5,16.8};
//模板实参推演期间决定模板实参的类型时,编译器不考虑函数模板实例的返回类型。
int il = min( da );

//当函数模板被调用时,对函数料参类型的检查决定了模板实参的类型和值,称为模板实参推演。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值