设为首页 加入收藏

TOP

PKU C++程序设计实习 学习笔记4 运算符重载(二)
2015-11-21 01:01:04 来源: 作者: 【 】 浏览:7
Tags:PKU 程序设计 实习 学习 笔记 运算 重载
oid 好不好?
考虑: a = b = c;
//等价于a.operator=(b.operator=(c));String 好不好?为什么是 String &
运算符重载时, 好的风格 -- 尽量保留运算符原本的特性
考虑: (a=b)=c; //会修改a的值
分别等价于:(a.operator=(b)).operator=(c);

5. 上面的String类是否就没有问题了?

?

为 String类编写 复制构造函数 时,会面临和 ‘=’ 同样的问题,用同样的方法处理

String::String(String & s)
{
  if(s.str) {
    str = new char[strlen(s.str)+1];
    strcpy(str, s.str);
  }
  else
    str = NULL;
}

4.3 运算符重载为友元函数

1. 运算符重载为友元

通常,将运算符重载为类的成员函数重载为友元函数的情况:
? 成员函数不能满足使用要求
? 普通函数,又不能访问类的私有成员
class Complex{
    double real, imag;
  public:
    Complex(double r, double i):real(r), imag(i){ };
    Complex operator+(double r);
};
Complex Complex::operator+(double r){ //能解释 c+5
  return Complex(real + r, imag);
}
经过上述重载后:
Complex c ;
c = c + 5; //有定义,相当于 c = c.operator +(5);
但是:
c = 5 + c; //编译出错
为了使得上述表达式能成立, 需要将+重载为普通函数
Complex operator+ (double r, const Complex & c) {
  //能解释 5+c
  return Complex( c.real + r, c.imag);
}
普通函数不能访问私有成员 —> 将运算符+重载为友元函数
class Complex {
    double real, imag;
  public:
    Complex( double r, double i):real(r),imag(i){ };
    Complex operator+( double r );
    friend Complex operator + (double r, const Complex & c);
};

4.4 实例 – 长度可变的整型数组类(可变长整型数组)

\
class CArray
{
    int size; //数组元素的个数
    int
    *ptr; //指向动态分配的数组
  public:
    CArray(int s = 0); //s代表数组元素的个数
    CArray(CArray & a);
    ~CArray();
    void push_back(int v); //用于在数组尾部添加一个元素v
    CArray & operator=( const CArray & a);
    //用于数组对象间的赋值
    int length() { return size; } //返回数组元素个数
    int & CArray::operator[](inti) //返回值为 int 不行!不支持 a[i] = 4
    {//用以支持根据下标访问数组元素,
     //如n = a[i]和a[i] = 4; 这样的语句
      return ptr[i];
    }
};

CArray::CArray(int s):size(s)
{
  if( s == 0)
    ptr = NULL;
  else
    ptr = new int[s];
}
CArray::CArray(CArray & a) 
{
  if( !a.ptr) {
    ptr = NULL;
    size = 0;
    return;
  }
  ptr = new int[a.size];
  memcpy( ptr, a.ptr, sizeof(int ) * a.size);
  size = a.size;
}
\

因为我们不写赋值构造函数的话,编译器自动生成的那个赋值构造函数会执行赋值的功能。这里所说的赋值的工作,只是把a1的成员变量赋值到a2里面去。那a1的成员变量ptr
被赋值到a2里面去,那自然a2.ptr就等于a1.ptr。那也就是说,a2的ptr和a1的ptr都指向了同一片存储空间。
CArray::~CArray()
{
  if( ptr) delete [] ptr;
}

CArray & CArray::operator=( const CArray & a)
{ //赋值号的作用是使“=”左边对象里存放的数组,大小和内容都和右边的对象一样
  if( ptr == a.ptr) //防止a=a这样的赋值导致出错
    return * this;
  if( a.ptr == NULL) { //如果a里面的数组是空的
    if( ptr ) delete [] ptr;
    ptr = NULL;
    size = 0;
    return * this;
  }
  if( size < a.size) { //如果原有空间够大,就不用分配新的空间
?  if(ptr) delete [] ptr;
?  ptr = new int[a.size];
  }
  memcpy( ptr,a.ptr,sizeof(int)*a.size);
  size = a.size;
  return * this;
} // CArray & CArray::operator=( const CArray & a)

void CArray::push_back(int v)
{ //在数组尾部添加一个元素
?if( ptr) {
?  int * tmpPtr = new int[size+1]; //重新分配空间
?  memcpy(tmpPtr,ptr,sizeof(int)*size); //拷贝原数组内容
?  delete [] ptr;
?  ptr = tmpPtr;
?}
?else //数组本来是空的
?  ptr = new int[1];
?ptr[size++] = v; //加入新的数组元素
}

4.5 流插入运算符和流提取运算符的重载

1. 问题

cout << 5 << “this”;为什么能够成立?

cout是什么?“<<” 为什么能用在 cout上?

2. 流插入运算符的重载

cout 是在 iostream 中定义的,ostream 类的对象。

“<<” 能用在cout 上是因为,在iostream里对 “<<” 进行了重载。

考虑,怎么重载才能使得cout << 5; 和 cout << “this”都能成立?

有可能按以下方式重载成 ostream类的成员函数:

void ostream::operator<<(int n)
{
  …… //输出n的代码
  return;
}

?

因为ostream已经封装好了,不可能把这个重载写成成员函数,所以写成全局函数。

cout << 5 ; 即 cout.operator<<(5);
cout << “this”; 即 cout.operator<<( “this” );

怎么重载才能使得cout << 5 << “this” ;成立?

ostream & ostream::operator<<(int n)
{
  …… //输出n的代码
  return * this;
}
ostream & ostream::operator<<( const char * s )
{
  …… //输出s的代码
  return * this;
}
cout << 5 << “this”;本质上的函数调用的形式是什么?
cout.operator<<(5).operator<<(“this”);

?

假定下面程序输出为 5hello, 该补写些什么

class CStudent{
  public: int nAge;
};
int main(){
  CStudent s ;
  s.nAge = 5;
  cout << s <<"hello";
  return 0;
}
ostream & operator<<( ostream & o,const CStudent & s){
  o << s.nAge ;
  return o;
}

?

3. 例题

?

(教材P218)例子。可略了。

?




 
首页 上一页 1 2 下一页 尾页 2/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇poj2728--Desert King(最优比率.. 下一篇[ACMcoder] A + B Problem II

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: