免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 4452 | 回复: 15
打印 上一主题 下一主题

[C++] 成员函数返回对象还是引用 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-11-05 16:24 |只看该作者 |倒序浏览
本帖最后由 andy_hqj 于 2013-11-05 17:51 编辑

首先附上代码
1、str.h
class String
{
        char * data;

public:
        String(char * str);
        String(String &s);
        ~String();
        String & operator=(String &s);
        String operator+(String &s);
};

2、str.cpp
#include <iostream>
#include "str.h"
#include <string.h>
using namespace std;

String::String(char *str)
{
        data=new char[strlen(str)+1];
        strcpy(data, str);
}

String::String(String &s)
{
        data=new char[strlen(s.data)+1];
        strcpy(data, s.data);
}
String::~String()
{
        delete [] data;
}
String & String:: operator=(String &s)
{
        if(this == &s)
                return *this;
        delete [] this->data;
        this->data = new char[strlen(s.data)+1];
        strcpy(this->data,s.data);
        return *this;
}
String String:: operator+(String &s)
{
        String tmp( "" );
        delete [] tmp.data ;
        tmp.data = new char[strlen(data)+strlen(s.data)+1];
        strcpy(tmp.data, data);
        strcat(tmp.data, s.data);
        return tmp;
}


3、测试函数 main.cpp
#include <iostream>
#include "str.h"
using namespace std;
int main()
{
        String s("hello" );
        String s1("world" );

        String s3("" );
        s3 = s + s1;
        return 0;
}


错误:
1、String s3("" );
        s3 = s + s1;
编译错误为:
main.cpp: In function ‘int main()’:
main.cpp:10: 错误:no match 为 ‘operator=’ 在 ‘s3 = String:: operator+(String& ) (((String& ) (& s1)))’ 中
str.h:9: 附注:备选为: String& String:: operator=(String& )
2、如果写成 String s3=s+s1;
编译错误为:
main.cpp:9: 错误:对 ‘String::String(String)’ 的调用没有匹配的函数
str.h:7: 附注:备选为: String::String(String& )
str.h:6: 附注:         String::String(char*)


但如果把重载+法运算符号的返回值改为引用,这两种方法都没问题(当然会提示返回局部变量地址)

那位帮忙解释一下,这两个错误的原因,我的环境为as5 gcc

论坛徽章:
14
巨蟹座
日期:2013-11-19 14:09:4615-16赛季CBA联赛之青岛
日期:2016-07-05 12:36:0515-16赛季CBA联赛之广东
日期:2016-06-29 11:45:542015亚冠之全北现代
日期:2015-07-22 08:09:472015年辞旧岁徽章
日期:2015-03-03 16:54:15巨蟹座
日期:2014-12-29 08:22:29射手座
日期:2014-12-05 08:20:39狮子座
日期:2014-11-05 12:33:52寅虎
日期:2014-08-13 09:01:31巳蛇
日期:2014-06-16 16:29:52技术图书徽章
日期:2014-04-15 08:44:01天蝎座
日期:2014-03-11 13:06:45
2 [报告]
发表于 2013-11-06 08:21 |只看该作者
一个 const修饰 也没有

论坛徽章:
59
2015年亚洲杯之约旦
日期:2015-01-27 21:27:392015年亚洲杯之日本
日期:2015-02-06 22:09:41拜羊年徽章
日期:2015-03-03 16:15:432015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:50:282015元宵节徽章
日期:2015-03-06 15:50:392015年亚洲杯之阿联酋
日期:2015-03-19 17:39:302015年亚洲杯之中国
日期:2015-03-23 18:52:23巳蛇
日期:2014-12-14 22:44:03双子座
日期:2014-12-10 21:39:16处女座
日期:2014-12-02 08:03:17天蝎座
日期:2014-07-21 19:08:47
3 [报告]
发表于 2013-11-06 08:31 |只看该作者
回复 2# bruceteen


    **好, 我没看出什么错误, **看出来没?
难道
operator+

const CLASS:perator+
才行?

好像没什么道理啊。

论坛徽章:
14
巨蟹座
日期:2013-11-19 14:09:4615-16赛季CBA联赛之青岛
日期:2016-07-05 12:36:0515-16赛季CBA联赛之广东
日期:2016-06-29 11:45:542015亚冠之全北现代
日期:2015-07-22 08:09:472015年辞旧岁徽章
日期:2015-03-03 16:54:15巨蟹座
日期:2014-12-29 08:22:29射手座
日期:2014-12-05 08:20:39狮子座
日期:2014-11-05 12:33:52寅虎
日期:2014-08-13 09:01:31巳蛇
日期:2014-06-16 16:29:52技术图书徽章
日期:2014-04-15 08:44:01天蝎座
日期:2014-03-11 13:06:45
4 [报告]
发表于 2013-11-06 08:33 |只看该作者
folklore 发表于 2013-11-06 08:31
回复 2# bruceteen

s+s1 是个临时String,不能被作为 String & operator=(String &s) 的参数,除非参数改为 const String& s
  1. class String
  2. {
  3. public:
  4.     String( const char* str );
  5.     String( const String& s );
  6.     ~String();
  7.     String& operator=( const String& s );
  8.     String operator+( const String& s ) const;
  9. private:
  10.     char* data_;
  11. };

  12. #include <cstring>

  13. String::String( const char* str )
  14. {
  15.     data_ = new char[strlen(str)+1];
  16.     strcpy( data_, str );
  17. }

  18. String::String( const String& s )
  19. {
  20.     data_ = new char[strlen(s.data_)+1];
  21.     strcpy( data_, s.data_ );
  22. }
  23. String::~String()
  24. {
  25.     delete[] data_;
  26. }
  27. String& String::operator=( const String& s )
  28. {
  29.     if( this == &s )
  30.         return *this;
  31.     delete[] data_;
  32.     data_ = new char[strlen(s.data_)+1];
  33.     strcpy( data_, s.data_ );
  34.     return *this;
  35. }
  36. String String:: operator+( const String& s ) const
  37. {
  38.     String tmp( "" );
  39.     delete[] tmp.data_;
  40.     tmp.data_ = new char[strlen(data_)+strlen(s.data_)+1];
  41.     strcpy( tmp.data_, data_ );
  42.     strcat( tmp.data_, s.data_ );
  43.     return tmp;
  44. }

  45. int main()
  46. {
  47.     String s("hello" );
  48.     String s1("world" );

  49.     String s3("");
  50.     s3 = s + s1;

  51.     return 0;
  52. }
复制代码

论坛徽章:
59
2015年亚洲杯之约旦
日期:2015-01-27 21:27:392015年亚洲杯之日本
日期:2015-02-06 22:09:41拜羊年徽章
日期:2015-03-03 16:15:432015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:50:282015元宵节徽章
日期:2015-03-06 15:50:392015年亚洲杯之阿联酋
日期:2015-03-19 17:39:302015年亚洲杯之中国
日期:2015-03-23 18:52:23巳蛇
日期:2014-12-14 22:44:03双子座
日期:2014-12-10 21:39:16处女座
日期:2014-12-02 08:03:17天蝎座
日期:2014-07-21 19:08:47
5 [报告]
发表于 2013-11-06 08:43 |只看该作者
回复 4# bruceteen


    有道理, 要改
  1. String& String::operator=( const String& s )
复制代码
就行了。

写过很多operator+ =, 都自动加上const了, 中毒太深~~

论坛徽章:
0
6 [报告]
发表于 2013-11-06 14:21 |只看该作者
本帖最后由 andy_hqj 于 2013-11-06 14:58 编辑

回复 4# bruceteen


如果把拷贝构造函数中的const去掉  编译时提示第10行,也就是  s3=s+s1;
main.cpp:10: 错误:对 ‘String::String(String)’ 的调用没有匹配的函数
str.h:9: 附注:备选为: String::String(String&)
str.h:8: 附注:         String::String(char*)

这里不是应该调用赋值运算符重载函数吗?这么会找构造函数的?

如果拷贝构造函数参数加上const 就能顺利通过,可执行的时候打印也没看到调用构造函数.
如果改成这样 String s3=s+s1; 同样没看到拷贝构造函数调用。这是为什么啊?(我在构造函数和拷贝构造中都加了打印)


   

论坛徽章:
17
处女座
日期:2013-08-27 09:59:352015亚冠之柏太阳神
日期:2015-07-30 10:16:402015亚冠之萨济拖拉机
日期:2015-07-29 18:58:182015年亚洲杯之巴勒斯坦
日期:2015-03-06 17:38:17摩羯座
日期:2014-12-11 21:31:34戌狗
日期:2014-07-20 20:57:32子鼠
日期:2014-05-15 16:25:21亥猪
日期:2014-02-11 17:32:05丑牛
日期:2014-01-20 15:45:51丑牛
日期:2013-10-22 11:12:56双子座
日期:2013-10-18 16:28:17白羊座
日期:2013-10-18 10:50:45
7 [报告]
发表于 2013-11-06 22:14 |只看该作者
回复 6# andy_hqj


    由于你的重载operator +的函数内部使用了String tmp( "" );而""这样的直接字符字面量实际上是const char*类型,它无法隐式转换为char*也无法隐式转换为string&,实际上可以转换为rvalue的char*,但此例中参数的char*以及string&都是lvalue。

论坛徽章:
36
子鼠
日期:2013-08-28 22:23:29黄金圣斗士
日期:2015-12-01 11:37:51程序设计版块每日发帖之星
日期:2015-12-14 06:20:00CU十四周年纪念徽章
日期:2015-12-22 16:50:40IT运维版块每日发帖之星
日期:2016-01-25 06:20:0015-16赛季CBA联赛之深圳
日期:2016-01-27 10:31:172016猴年福章徽章
日期:2016-02-18 15:30:3415-16赛季CBA联赛之福建
日期:2016-04-07 11:25:2215-16赛季CBA联赛之青岛
日期:2016-04-29 18:02:5915-16赛季CBA联赛之北控
日期:2016-06-20 17:38:50技术图书徽章
日期:2016-07-19 13:54:03程序设计版块每日发帖之星
日期:2016-08-21 06:20:00
8 [报告]
发表于 2013-11-06 23:02 |只看该作者
本人过去、现在以及将来都不认识楼主,且自古以来与楼主无利益关系。楼主表述之事与本人无关.

论坛徽章:
0
9 [报告]
发表于 2013-11-07 11:15 |只看该作者
回复 7# myworkstation


那你的意思是实际报错的是 String  tmp("");?
那String s("hello" );String s1("world" );这两句为什么没报这个错误呢?
如果是这句报错,那也应该是报 String(const char *)没有匹配的函数吧?



   

论坛徽章:
17
处女座
日期:2013-08-27 09:59:352015亚冠之柏太阳神
日期:2015-07-30 10:16:402015亚冠之萨济拖拉机
日期:2015-07-29 18:58:182015年亚洲杯之巴勒斯坦
日期:2015-03-06 17:38:17摩羯座
日期:2014-12-11 21:31:34戌狗
日期:2014-07-20 20:57:32子鼠
日期:2014-05-15 16:25:21亥猪
日期:2014-02-11 17:32:05丑牛
日期:2014-01-20 15:45:51丑牛
日期:2013-10-22 11:12:56双子座
日期:2013-10-18 16:28:17白羊座
日期:2013-10-18 10:50:45
10 [报告]
发表于 2013-11-07 16:16 |只看该作者
回复 9# andy_hqj


    你用的哪个编译器?假如我说的问题在你的编译器不存在,单独分析两次赋值:String s3=s+s1;这种方式叫copy initialize,需要调用copy构造函数,而String s3;s3=s+s1;这样的方式调用的是operator = ,当你把copy构造函数String::String( const String& s )中参数的const去掉变成String::String( String& s ),第一种方式肯定有问题String s3=s+s1,因为s+s1是个临时对象无法转换为lvalue引用。而第二种方式由于你重载的操作符String String:: operator+( const String& s ) const,返回的结果是个String,那么return tmp;是有问题的,因为tmp要copy到函数返回值中,而这个copy无法进行(函数返回值赋值处也有一个临时对象,原因同上临时对象无法转换为lvalue引用,所以operator+调用是失败的,错误提示没有准确的提示到),你改成String& String:: operator+( const String& s )这样的原型应该就不会出这个错误了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP