C++ Primer Plus读书笔记06
2012-03-04
1、重载运算符 例如Time类重载+
Time operator +(const Time input) { Time sum; sum.minute=input.minute+minute;;… return sum; } |
Time Sum(const Time &t) { …. return sum } |
两者功能一样,但左边是重载,可以实现Time a,b,c,d; a=b+c+d;这样的操作
重载后的操作符至少有一个是用户定义的类型(本例为time型),且优先级不变。∴不可重载+表示(double-double)
不可重载的操作符:sizeof,逗号,作用域运算符::,见P342
另外,=,[],(),→只能通过成员函数进行重载
(以上例子都是通过成员函数进行重载)
eg.重载*,表示一个时间*n倍
Time operator * (const int n){……}
问题:Time A,B; int n; A=B*n等价于A=B.operator*(n)
但A=n*B就会出错 左侧的运算符是调用对象 引出友元
2、友元:非成员函数进行重载
Time operator *(int n,const Time &t)
{ Time result;
result.minute=t.minute*n;……
return result;
}此函数可实现A=n*B,但此函数不可访问t.minute等私有成员
∴引入友元~将原型放在类声明中,并加friend(实现在,cpp中)
如friend Time operator *(int n,const Time &t);
友元不是成员函数,∴不可Time::operator这样调用,但可访问私有数据
3、常用的友元:重载<<
应用场合:例如Time a,b; cout<<a;
若用成员函数重载,第一个操作数应该为Time 类,形如a<<cout,不易理解
friend void operator << (iostream &os,const Time &t)
{os<<t.hours<<t.minutes}
//此函数是Time的友元,因为用到time.hours(private),但不是ostream的友元,os作为一个整体出现。∴不访问对象的私有成员便可以不是此类友元
此时,cout<<a正常,但cout<<a<<b不正常;
改正思路:使cout<<a变为一个ostream对象,所以更改变量为
friend ostream& operator << (iostream &os,const Time &t)
{…… return os; }
4、只有一个参数的构造函数可以以赋值形式初始化→用作自动类型转换
Myclass test=10;相当于Myclass test=Myclass(10);
可以用关键字explicit关闭这项特性 explicit Myclass(int n);
则左边错,右边对
类中的转换函数,将类类型转换为常见类型 见P368,P374
5、class stringbad
{
char *str; int len; static int num_string;
}//则类的每个对象都有一个自己的str,len,所有类对象共用一个num_string
6、C++自动提供默认构造函数,复制构造函数,赋值运算符和默认析构函数
复制构造函数举例:class test (copy); class test=copy; class test=class(copy) class *test=new class (copy);//默认的复制构造函数为按值传递
∴复制的不是字符串,而是指向字符串的指针
eg stringbad b=a;//则a.str与b.str指向同一处地址。对a析构后,b.str已经被释放 很危险。
解决方案:使用显式构造函数进行深复制,复制str的副本,而非指针(默认为浅复制)
实现:stringbad::stringbad(const stringbad &st)
{
len=st.len; str=new char[str+1]; //深复制
strncpy(str,st.str);
}
若类中包含使用new初始化的指针成员,则应定义一个复制构造函数,实现深复制(如上) //默认构造函数是浅复制,只复制指针指
赋值运算符会导致同样的问题
stringbad a; a=b; //则a.str与b.str指向同一处地址
解决方案:提供赋值操作符定义(与复制构造函数有3出区别)
stringbad & stringbad::operator=(const stringbad &st)
{
if(this==&st) return *this //(1)函数应避免将对象赋给自身 否则对象重新赋值前,可能会删除对象的内容,参见(2)
delete [] str; //(2)由于目标对象可能引用了以前分配的数据∴应释放
len=st.len; str=new char [len+1]; strncpy(str,st.str);
return *this //(3)返回调用对象的引用,可以实现a=b=c=d这样的操作
} 详见P389