Effective C++读书笔记02
2012-03-27
1、在operator=中为所有成员赋值
例如,base中有private x,derived中有private y
则,derived & operator=(const derved& r)
{ if(this==&r) return *this;
y=r.y; return *this;
}//错,因为base成员中的x并未赋值,但由于x为base的private,在子类中无法赋值
解决方案:在y=r.y之前加入base::operator=(r);//调用base的=重载
若base中未写operator=,则会报错,如果是这种情况,更改为
static_cast<base&>(*this)=r; //通过一个强制类型转换来实现
同理,复制构造函数也应如此(不过必须要使用初始化列表的方式,不要用在函数内赋值的方式)
形如class derived:public base
{
public :
derived(const derived*r):base(r),y(r.y)//这样写复制构造函数
{
}
}
2、operator=中检测是否自己赋给自己
例如类string private:char * data;
string &operator=(const string&r)
{ delete []data;
data=new char[r.length+1]; strcpy(data,r.data); return *this; }
若a=”hello”,执行a=a,则上述会把hello删除,后果严重
安全写法为:
{
if(this==&r) return *this;
delete []data;
…… //如果是自己赋给自己,直接返回,不会误删
}
3、explicit作用:拒绝隐式转换
例如分数类const Rational operator*(const Rational &r)const;
{……
}
Rational result,half;
则result=half*2正确→相当于result=onehalf.operator*(2)
此时2虽然不满足函数形参匹配条件(不是rational类型),但编译器会调用隐式类型转换,即相当于
const Rational temp(2);
result=halt*temp;
但若在构造函数中加入explicit,如
explicit Rational(int number=0,int number2=1)
则result=half*2会报错,不会隐式转换
为解决result=2*half报错的问题,让operator*成为一个非成员函数,则编译器会在每个参数上都执行隐式转换,若无必要成为友元,就不必friend
准则:1,虚函数必须是class member
2,不要让operator>>或者operator<<成为class member(class member只能让使用者在前),否则只能用string<<cout;这样的形式
∴,使用非成员变量(调用者在前在后都可以),若 函数需用到非公有成员,则设为友元
3,只有非成员函数才会在每个参数上都执行隐式转换,形如time2=2*time1格式才会正确,同上,若用到非公有成员,则设为友元
4,除上述外,都设为成员函数,即,能不友元就不用友元
4、在C++中,”hello”是const char []型(或被视为const char *型),∴将其作为char 变量初值不合适(const不匹配)
C中频繁使用,C++中避免这样做
5、mutable作用:让费静态成员变量可在const说明中修改
举例:Class Base{int a,b;};
若有int Base::value()const //成员函数,最后的const表示此方法不会修改成员变量值
{
a=3,b=1;
}//出错
若在声明时加入mutable int a; mutable int b; 则成员函数不会出错