Effective C++ 24,25

24.在函数重载和设定參数缺省值间要谨慎选择。

获得一种类型的数据的最小值或最大值,对于c中,一般使用在<linits.h>中定义的各种宏如INT_MIN 来进行表示,可是这样无法进行泛型编程。即相应怎样一种类型T返回相应类型的最小或最大值。

而在c++中一般如此获得

std::numeric_limits<T>::min()
c++在<limits>中定义了类模版numeric_limits,用来返回相应类型的最小最大值。这是一个非常实用的东西。

然后继续讨论函数重载与參数缺省值,例如以下面情况:

int fun(){
	return 1;
}
int fun(int a){
	return a;
}
int fun(int a=1,int b = 0){
	return a+b;
}
对于第3个函数,当没有參数和仅仅有一个參数时会与前两个函数冲突,可是对于第三个函数,即有默认值的情况下。其能直接具有所有三个函数的功能。使用默认值的函数其效果更好且功能很多其它。

可是有时找不到一个好的缺省值。当对5个以内的值求和时,能够设每一个參数的默认值为0,可是当对5个以内的值进行求平均数时,要获得传入參数的个数,无法通过函数的參数来实现,所以仅仅能重载5个函数,即仅仅有一个,两个,3。4,5个函数的全部情况。

还有一种必须使用重载函数的情况是:想完毕一项特殊的任务,但算法取决于给定的输入值。就是说函数因为输入參数不同进行操作不同的这类函数要重载,如类的构造函数。


25.避免对指针和数字类型的重载。

如函数 void f(int x);和void f(int * p);这两个函数的。重载是会出错。简单来说对于实參为0,即0是什么?0即是指针有是int。但其实在编译器中执行

void f(int* x){
	cout<<"int_ptr"<<endl;
}
void f(int x){
	cout<<"int"<<endl;
}
int main(){
	f(NULL);

结果为 输出 int ,即0是一个int。人们觉得一个调用具有多义性时,编译器却不这么干。

NULL的类型是就是int,要使其调用 f(int*)这个函数,就必须如此做

	f(static_cast<int*>(NULL));
可是假设将NULL定义为UL。即无符号整数

#define NULL 0UL
在调用f(NULL)又会报错。重载不明白,NULL即能够是int也能够是int*

可是假设又将f(int)函数改为

void f(unsigned long x)。
又会正确,由于NULL是unsigned long。而f函数中參数也是。

而假设我们须要一个不论什么地方都能够使用的随意类型的NULL指针。就必须设计一个产生NULL指针对象的类:

#ifdef NULL
#undef NULL
#endif
class NullClass{
public:
	template<class T> //模版
	operator T*()const{return 0;}//返回一个T*的null指针。

}; const NullClass NULL;//NULL的常量

然后再次使用 f(NULL)的时候,就会调用隐式的类型转换,获得一个对象T类型的null指针。可是这样还不够。改进:

首先我们仅仅须要一个NullClass对象,所以给这个类一个名字是没有必要的,定义一个匿名类并使NULL成为这样的类型。

其次。我们想让NULL可以转换为怎样类型的指针。那就要可以处理成员指针(指 指向类中函数的指针),要再定义一个成员模版,将类C与全部类型T转换为类型 T C::*。

最后要防止用户取NULL的地址,NULL要表现的像指针一样,但其值不是指向真正的0,所以要对用户隐藏。

改进后例如以下:

class {
public:
	template<class T> //模版
	operator T*()const{return 0;}//返回一个T*的null指针。
	template<class C,class T>
	operator T C::*() const{return 0;}//转换随意类型的null成员指针
private:
	void operator&() const ;//隐藏NULL的地址
}NULL; //仅仅有一个名字为NULL的对象









你可能感兴趣的:(Effective C++ 24,25)