BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / cpp / #25989同步于 2009/7/8
CPP机器人发帖

[合集] 【求助】问个操作符重载的问题

shenlei
2009/7/8镜像同步0 回复
☆─────────────────────────────────────☆ houdao (北邮人) 于 (Mon Jul 14 22:08:01 2008) 提到: 错误: Person.h中 friend ostream& operator<<(ostream& o,const Person& p); Person.cpp中 inline ostream& operator<<(ostream& o,const Person& p) { return o<<p.name<<"\n"; } 正确: Person.h中 friend inline ostream& operator<<(ostream& o,const Person& p) { return o<<p.name<<"\n"; } main函数中 Person person2; person2.setName("jimmy"); cout<<person2; 上面两种方式的区别在哪里?为什么第一种出错呢,望达人指点 ☆─────────────────────────────────────☆ Xer (SL小分队|小x|benogy) 于 (Mon Jul 14 22:13:43 2008) 提到: 我记得内联函数的定义和声明不能分开,要写在一块。 【 在 houdao (北邮人) 的大作中提到: 】 : 错误: : Person.h中 : friend ostream& operator<<(ostream& o,const Person& p); : ................... ☆─────────────────────────────────────☆ rebirthatsix (茫犭者-算法盲) 于 (Mon Jul 14 22:15:26 2008) 提到: 【 在 Xer 的大作中提到: 】 : 我记得内联函数的定义和声明不能分开,要写在一块。 re ☆─────────────────────────────────────☆ houdao (北邮人) 于 (Mon Jul 14 22:17:18 2008) 提到: 哦,太感谢了! 【 在 Xer 的大作中提到: 】 : 我记得内联函数的定义和声明不能分开,要写在一块。 ☆─────────────────────────────────────☆ ericyosho (ericyosho) 于 (Mon Jul 14 22:57:15 2008) 提到: 晕,谁说不可以的,当然可以啦。 我怎么感觉一直都是可以的呢。 而且已经测试了,显然是可以的。 ☆─────────────────────────────────────☆ Xer (SL小分队|小x|benogy) 于 (Mon Jul 14 23:10:15 2008) 提到: 我记得以前有人问过这个问题,当时试了下是不可以的。能把你的例子贴一下吗? 【 在 ericyosho (ericyosho) 的大作中提到: 】 : 晕,谁说不可以的,当然可以啦。 : 我怎么感觉一直都是可以的呢。 : 而且已经测试了,显然是可以的。 : ................... ☆─────────────────────────────────────☆ houdao (北邮人) 于 (Mon Jul 14 23:43:03 2008) 提到: 第一种不加cout<<person2;编译能通过,加上这句就报错。。。。。 【 在 ericyosho 的大作中提到: 】 : 晕,谁说不可以的,当然可以啦。 : 我怎么感觉一直都是可以的呢。 : 而且已经测试了,显然是可以的。 ☆─────────────────────────────────────☆ ericyosho (ericyosho) 于 (Mon Jul 14 23:49:10 2008) 提到: 1.h class B { public: void f() const; }; 1.cc #include <iostream> #include "1.h" using namespace std; inline void B::f()const { cout << "kua zhang" << endl; } int main() { B b; b.f(); return 0; } ☆─────────────────────────────────────☆ houdao (北邮人) 于 (Tue Jul 15 00:06:21 2008) 提到: Person.h #pragma once #include <string> #include <iostream> using namespace std; class Person { string name; public: Person(void); public: ~Person(void); public: void setName(string const name); friend ostream& operator<<(ostream& o,const Person& p); }; Person.cpp #include "StdAfx.h" #include "Person.h" Person::Person(void) { } Person::~Person(void) { } void Person::setName(string const name) { this->name=name; } inline ostream& operator<<(ostream& o,const Person& p) { return o<<p.name<<"\n"; } main #include "stdafx.h" #include <iostream> #include "Person.h" using namespace std; int _tmain(int argc, _TCHAR* argv[]) { Person person2; person2.setName("jimmy"); cout<<person2; //加上这句就报错 return 0; } ☆─────────────────────────────────────☆ houdao (北邮人) 于 (Tue Jul 15 00:08:37 2008) 提到: 1>first.obj : error LNK2019: 无法解析的外部符号 "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl operator<<(class std::basic_ostream<char,struct std::char_traits<char> > &,class Person const &)" (??6@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@ABVPerson@@@Z),该符号在函数 _wmain 中被引用 1>D:\VSWorkplace\first\Debug\first.exe : fatal error LNK1120: 1 个无法解析的外部命令 ☆─────────────────────────────────────☆ ericyosho (ericyosho) 于 (Tue Jul 15 08:21:15 2008) 提到: 你这个不是编译错误,是链接错误。 编译已经通过了。 我不知道具体是什么原因的,感觉应该是工程的设置引起的。 你看,它提到了_wmain,所以你的工程应该是建立在UNICODE模式下的。 所以你能不能使用cout和string呢?还是必须使用wcout和wstring呢?(最近一直在弄国际化的问题,所以比较敏感,真实原因请自行尝试,可以把工程里面的UNICODE和_UNICODE选项去掉,换成_MBCS) 下面是我在gcc下面的代码,和你的一样,只是把windows特有的头文件stdafx都去掉了。而且没有工程的限制,可以输出正确的答案。 Person.h #pragma once #include <iostream> using namespace std; class Person { string name; public: void setName(string const &name); friend ostream& operator<<(ostream& o,const Person& p); }; Person.cpp #include <iostream> #include "Person.h" using namespace std; void Person::setName(const string &name) { this->name = name; } inline ostream& operator<<(ostream& o, const Person &p) { return o << p.name << "\n"; } int main() { Person person2; person2.setName("jimmy"); cout << person2; return 0; } ☆─────────────────────────────────────☆ houdao (北邮人) 于 (Tue Jul 15 10:05:44 2008) 提到: 十分感谢,我再试试 【 在 ericyosho 的大作中提到: 】 : 你这个不是编译错误,是链接错误。 : 编译已经通过了。 : 我不知道具体是什么原因的,感觉应该是工程的设置引起的。 : ................... ☆─────────────────────────────────────☆ loop (忧郁&&委屈!) 于 (Tue Jul 15 15:43:14 2008) 提到: 我把 inline ostream& operator<<(ostream& o,const Person& p) { return o<<p.name<<"\n"; } inline去掉就没有连接错误了 【 在 houdao (北邮人) 的大作中提到: 】 : 1>first.obj : error LNK2019: 无法解析的外部符号 "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl operator<<(class std::basic_ostream<char,struct std::char_traits<char> > &,class Person const &)" (??6@YAAAV?$basic_ostream@DU?$c : 1>D:\VSWorkplace\first\Debug\first.exe : fatal error LNK1120: 1 个无法解析的外部命令 ☆─────────────────────────────────────☆ ericyosho (ericyosho) 于 (Tue Jul 15 16:03:42 2008) 提到: 如果真是inline的话,是不是更加诡异了呢? 因为据我所知,inline只是给编译器的一个提示。 编译器完全可以选择inline还是outline =。= ☆─────────────────────────────────────☆ wks (cloverprince) 于 (Tue Jul 15 16:06:19 2008) 提到: 内联函数当然要和调用在同一个文件里(或者include进去) 内联函数在“编译”阶段将函数调用和函数本体绑定。 设想,一个函数在person.h里声明,函数体在person.cpp里, 当编译main.cpp(include person.h)的时候,编译器需要把这个函数的函数体插入到调用的位置, 但是函数体既不在main.cpp里,又不在person.h里,编译器到哪里去找它呢? 注意:编译main.cpp的时候,编译器是不会理睬person.cpp的,甚至person.cpp不存在都可以。 ☆─────────────────────────────────────☆ ericyosho (ericyosho) 于 (Tue Jul 15 16:17:14 2008) 提到: 那7楼的例子,怎么解释? 其实我觉得,只要在.h文件中有声明就可以了。 是否inline是可以在.cpp具体实现的时候由程序员进行选择的,而且编译器只是参考一下你的意见,不一定能够执行。 ☆─────────────────────────────────────☆ loop (忧郁&&委屈!) 于 (Tue Jul 15 16:32:03 2008) 提到: 这个弄成inline的有啥好处? ☆─────────────────────────────────────☆ ericyosho (ericyosho) 于 (Tue Jul 15 16:34:52 2008) 提到: 呵呵,是看不出有什么。 只是不要逃避问题么。 这样在真要用的时候,就知道答案了。 ☆─────────────────────────────────────☆ wks (cloverprince) 于 (Tue Jul 15 18:39:53 2008) 提到: 用g++ -S看,7楼的例子也会把那个b.f调用变成一条call指令 但是不知道那是不是最终的代码,编译器会不会继续优化。 ☆─────────────────────────────────────☆ ericyosho (ericyosho) 于 (Tue Jul 15 20:02:15 2008) 提到: 搞清楚了,向大家汇报一下。由LZ来最后确认一下,就可以结贴了。 首先,7楼的那个代码,最后确实是展开了,inline成功。 wks说,使用gcc -S 查看汇编,并没有展开,而是仍然使用了call指令。 我对其进行了优化,gcc -S -O3,可以看到生成的.s文件只有原来的一半,而且再查看_main函数段,已经没有call指令了,由内联的语句所代替。 这就证明了,inline函数的定义(非声明)确实是既可以放在.h文件中,也可以放在.cc文件中,这都是没有问题的。而且编译器也都会正常处理。 但正如wks所说,inline函数的定义(非声明)在调用处必须是可见的。那么我们可以直接放在.cc文件中,就如7楼的代码一样。也可以放入.h文件中,然后在要使用的.cc文件中#include进去。 现在有一个问题,就是如果a.cc和b.cc同时都要调用inline函数,若将inline函数的定义放入.h文件,则只需要在a.cc和b.cc中包含该.h文件即可。若想分别放在a.cc和b.cc中,就要由程序员保证,在a.cc和b.cc中的两个定义是完全一致的。否则,编译器只会随机挑选其中的一个进行内联。 因此,将inline函数的定义放入.h文件中,并不是必须的,而是为了防止在多份.cc文件中inline定义的不一致。 LZ所碰到的问题,恰恰是犯了这个错误,LZ的代码,在main文件中,无法找到inline函数的定义(非声明),因此出错。这也是loop所说,为何将inline去掉以后,就能链接成功的原因。 至于一开始我猜测的宽窄字符的问题,是经不住时间和论证考验的,是注定错误的。 =。= 完毕。
订阅后,新回复会通过你的通知中心匿名送达。
0 条回复
暂无回复 · 你可以订阅本帖等待新回复。