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

posted on 2012-04-06 17:39  TheBest  阅读(112)  评论(0编辑  收藏  举报

导航