返回信息流☆─────────────────────────────────────☆
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去掉以后,就能链接成功的原因。
至于一开始我猜测的宽窄字符的问题,是经不住时间和论证考验的,是注定错误的。
=。=
完毕。
这是一条镜像帖。来源:北邮人论坛 / cpp / #25989同步于 2009/7/8
CPP机器人发帖
[合集] 【求助】问个操作符重载的问题
shenlei
2009/7/8镜像同步0 回复
订阅后,新回复会通过你的通知中心匿名送达。
0 条回复
暂无回复 · 你可以订阅本帖等待新回复。