首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

关于在重载赋值操作符,返回值为非 const对象引用值 的有关问题

2012-11-09 
关于在重载赋值操作符,返回值为非 const对象引用值 的问题。问题描述:看到《C++ Primer Plus》12章,12.1.5-有

关于在重载赋值操作符,返回值为非 const对象引用值 的问题。
问题描述:
看到《C++ Primer Plus》12章,12.1.5-有关返回对象的说明的时候,见到里面关于 返回指向非const对象的引用 的问题,里面提到两种常见的返回非const对象的引用,其中就有重载赋值操作符。
原文大意:
String s1 ("Good stuff");
String s2,s3;
s3=s2=s1;
在这个例子中,返回类型不是const,因为方法operator=()返回一个指向s2的引用,可以对其修改。

============================分割线
我自己写了个例子,将重载赋值操作符的返回值 改为 const ,好像也可以,这是咋么回事啊??
代码如下:
头文件:
#ifndef STOCK_H_
#define STOCK_H_
#include <iostream>
class Stock
{  
  private:
  int len; //新增加成员; 
  char *company;
  int shares;
  double shares_val;
  double total_val;
  void set_tot() {total_val=shares*shares_val;}
  public:
  Stock();
  Stock(const char *co,int n=0,double pr=0.0);
  Stock (const Stock & st); //新增加复制构造函数;
  Stock (const char *s); //新增加转换函数;
  const Stock & operator= (const Stock &st); //新增加重载赋值操作符;
  friend std::ostream & operator<< (std::ostream &os,const Stock &st); 
  const Stock & operator= (const char *s);
  ~Stock();
  void buy (int num,double price);
  void sell (int num,double price);
  void update (double price);
  //void show() const;
  const Stock & topval(const Stock &s) const;  
};

#endif

========================分割线
实现文件:
#include <iostream>
#include "stock.h"

Stock::Stock()
{
  len=8;
  company=new char [len];
  std::strcpy(company,"no name");
  shares=0;
  shares_val=0;
  total_val=0;
}

Stock::Stock(const char *co,int n,double pr)
{
  len=std::strlen(co);
  company=new char [len+1];
  std::strcpy(company,co);
  if (n<0)
  {
  std::cerr<<"Number of shares can't be negative."
  <<company<<"shares set to 0 .\n";
  shares=0;
  }
  else
  shares=n;
  shares_val=pr;
  set_tot();
}

Stock::Stock (const Stock & st)
{
  delete [] company;
  len=std::strlen(st.company);
  company=new char [len+1];
  std::strcpy(company,st.company);
  shares=st.shares;
  shares_val=st.shares_val;
  total_val=st.total_val;


Stock::Stock (const char *s) 
{
  delete [] company;
  len=std::strlen(s);
  company=new char [len+1];
  std::strcpy(company,s);
}

 const Stock & Stock::operator= (const Stock &st)
{
  if (this==&st)
  return *this;
  delete [] company;
  len=std::strlen(st.company);
  company=new char [len+1];
  std::strcpy(company,st.company);
   
  shares=st.shares;
  shares_val=st.shares_val;
  total_val=st.total_val;
  return *this;
}

const Stock & Stock::operator= (const char *s)
{
  delete [] company;


  len=std::strlen(s);
  company=new char [len+1];
  std::strcpy(company,s);

  return *this;  
}

Stock::~Stock()
{
  delete [] company;
}

void Stock::buy (int num,double price)
{
  if (num<0)
  {
  std::cerr<<"Number of shares purchased can't be negative."
  <<"Transaction is aborted.\n";
  }
  else
  {
  shares+=num;
  shares_val=price;
  set_tot(); 
  }
}

void Stock::sell (int num,double price)
{
  using std::cerr;
  if (num<0)
  {
  cerr<<"Number of shares sold can't be negative. "
  <<"Transaction is aborted.\n";
  }
  else if (num>shares)
  {
  cerr<<"You can't sell more than you have! "
  <<"Transaction is aborted.\n";
  }
  else
  {
  shares-=num;
  shares_val=price;
  set_tot();
  }
}

void Stock:: update (double price)
{
  shares_val=price;
  set_tot();
}

const Stock & Stock::topval(const Stock &s) const
{
  if (s.total_val>total_val)
  return s;
  else
  return *this;
}

std::ostream & operator<< (std::ostream &os,const Stock &st)
{
  os<<"Company"<<st.company
  <<" Shares: "<<st.shares<<std::endl
  <<" Shares Price: $"<<st.shares_val
  <<" Total Worth: $"<<st.total_val<<std::endl;
  return os;
   
}

====================主函数

#include "stock.h"
#include <iostream>
#include <cstdlib>


int main()
{
  using std::cout;
  Stock s1("test",5000,32.0);
  Stock s2("test-s2",1000,12.3);
  Stock st2;
  Stock st3;
  st3=st2=s1;
  st3=s2;
  std::cout<<st2<<std::endl;
  std::cout<<st3<<std::endl;

  system("pause");
}



[解决办法]
重载操作符应当参照内建数据类型(如int)的行为。
返回string&与const string&是有本质区别的:前者为左值,后者为右值。
对于 = 操作符,因其运算顺序为从右至左,所以LZ的测试代码没有发现问题,但如果运算顺序为从左至右,那么区别马上体现,如下:
(s1=s2)=s3;

(s1=s2).update(15.5);
这时,你会发现编译通不过。

热点排行