Tauruser
Enjoy Every Day
posts - 34, comments - 95, trackbacks - 0, articles - 5
C++博客
::
首页
::
新随笔
::
联系
::
聚合
::
管理
为什么在VS2005重载输出运算符那么难?
Posted on 2006-03-14 23:48
Tauruser
阅读(1653)
评论(7)
编辑
收藏
引用
所属分类:
算法与数据结构
最近在VS2005下实现一个模版堆栈时,想重载一下输出运算符。结果老是遇到问题,如何都过不去,想不想去都不明白。还望高手指教。
一开始同样的程序在VC2005和VC6.0下编译都没问题,但是一到链接的时候就出现问题了。都提示如下错误:
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 SegStack<int> const &)
"
(
??
6
@YAAAV
?
$basic_ostream@DU
?
$char_traits@D@std@@@std@@AAV01@ABV
?
$SegStack@H@@@Z),该符号在函数 _main 中被引用
死活都运行不了。后来发现如果在程序中不使用“cout<<”重载的运算符进行输出,在两个平台下都没有问题。可以重载的方式我已经全部按语法写了。
今晚,又在VC6.0下再生成一次,奇迹般成功了。(PS:难道今晚的RP比较高 ^-^)但是还是没有解决在VC2005下的问题,还是提示如上错误,VC2005到底还改了什么,与VC6.0不同了?一模一样的程序,为什么在VC2005下都不行,在VC2005下的重载输入输出应该如何应该如何?
下面贴一下例程,麻烦有时候的大牛帮我看一下,很简单的一个程序。
Ex2_2.rar
里面有三个文件分别如下:(ex2_2.cpp,stack.cpp,stack.h)下面贴一下文件的内容。
/**/
/////////
/ex2_2.cpp
/////////
//
//////////////////////////////
#include
"
stack.cpp
"
SegStack
<
int
>
iStack(
10
);
int
main()
{
for
(
int
i(
0
);i
<
10
;i
++
)
iStack.push(i);
cout
<<
iStack;
iStack.output(cout);
for
(i
=
0
;i
<
5
;i
++
)
iStack.pop();
cout
<<
iStack;
return
0
;
}
/**/
/////////
//stack.h
/////////
/
//////////////////////////////
/
#ifndef stack_h_
#define
stack_h_
#include
<
iostream
>
using
namespace
std;
template
<
class
T
>
class
stack
{
public
:
virtual
void
push(
const
T
&
x)
=
0
;
virtual
void
pop()
=
0
;
virtual
T Top()
const
=
0
;
virtual
bool
IsEmpty()
const
=
0
;
virtual
bool
IsFull()
const
=
0
;
}
;
template
<
class
T
>
class
SegStack:
public
stack
<
T
>
{
public
:
SegStack(
int
mSize);
~
SegStack();
bool
IsEmpty()
const
;
bool
IsFull()
const
;
void
push(
const
T
&
x);
void
pop();
T Top()
const
;
friend ostream
&
operator
<<
(ostream
&
out
,
const
SegStack
<
T
>&
seg);
void
output(ostream
&
out
)
const
;
private
:
T
*
s;
int
maxSize;
int
top;
}
;
#endif
/**/
////////////
stack.cpp
////////////
/////////////////////////////////
//
#include
"
stack.h
"
template
<
class
T
>
SegStack
<
T
>
::SegStack(
int
mSize):top(
-
1
)
{
maxSize
=
mSize;
s
=
new
T[maxSize];
}
template
<
class
T
>
SegStack
<
T
>
::
~
SegStack()
{
delete []s;
}
template
<
class
T
>
bool
SegStack
<
T
>
::IsFull()
const
{
return
(top
==
(maxSize
-
1
));
}
template
<
class
T
>
bool
SegStack
<
T
>
::IsEmpty()
const
{
return
(top
==-
1
);
}
template
<
class
T
>
void
SegStack
<
T
>
::push(
const
T
&
x)
{
if
(IsFull())
{
cout
<<
"
The stack is full
"
<<
endl;
}
else
{
s[
++
top]
=
x;
}
}
template
<
class
T
>
void
SegStack
<
T
>
::pop()
{
if
(IsEmpty())
{
cout
<<
"
The stack is empty
"
<<
endl;
}
else
{
top
--
;
}
}
template
<
class
T
>
T SegStack
<
T
>
::Top()
const
{
return
s[top];
}
template
<
class
T
>
void
SegStack
<
T
>
::output(ostream
&
out
)
const
{
out
<<
"
The stack list is:
"
;
for
(
int
i(
0
);i
<=
top;i
++
)
out
<<
"
"
<<
s[i];
out
<<
endl;
}
template
<
class
T
>
ostream
&
operator
<<
(ostream
&
out
,
const
SegStack
<
T
>&
seg)
{
out
<<
"
The stack list is:
"
;
for
(
int
i(
0
);i
<=
seg.top;i
++
)
out
<<
"
"
<<
seg.s[i];
out
<<
endl;
//
seg.output(out);
return
out
;
}
在最后,我还想问的一个问题是:为什么在ex2_2.cpp里#include "stack.h"时会无法编译通过,而#include "stack.cpp"时就可以了呢?
记得我刚学C++的时候,老师跟我说把头文件和源程序文件分开,最主要的是要进行知识产权保护,当你写好一个子程序时,发布就不要给对方源程序,只要给对方头文件和编译过来的相应obj文件就可以了。但是从上面的例子上看来,如果不#include "stack.cpp"就无法编译通过,这不就代表一定要给源程序对方吗?为什么会这样子的。我应该如何做呢?如果我想实现源程序的保存。
Feedback
#
re: 为什么在VS2005重载输出运算符那么难?
回复
更多评论
2006-03-15 01:16 by
dhong
class SegStack里面这么写:
template < class T1 >
friend ostream& operator << (ostream& out,const SegStack<T1>& seg);
这个operator不是SegStack的成员,因此不多写一个template这个operator就不是template的了
template的申明和定义一般都放入.h中,而不是.cpp,原因之一是template需要被实例化时必须保证编译器能找到实现
反过来想,如果template的定义都在.cpp中,那这个cpp被编译时至多产生一种T的实现(多半不会产生实际代码,编译器根本无从知晓T到底是什么类型),那么不妨假设其他cpp中有至少两种不同的T,那么编译器该如何连接呢?呵呵
因此目前为止,几乎所有编译器都要求需要展开template时能找到定义,于是形成了template定义不放在.cpp中的惯例
#
re: 为什么在VS2005重载输出运算符那么难?
回复
更多评论
2006-03-15 12:03 by
Tauruser
真的可以了,困挠我一个星期的问题终于解决了,顺便再问一下,为什么在VC6.0里不用再多加一个template <class T1>也可以成功运行呢?
#
re: 为什么在VS2005重载输出运算符那么难?
回复
更多评论
2006-03-15 21:16 by
dhong
不知道,这个要问ms,呵呵。vc6诞生的年代,c++标准关于模版的规定还很不完善,vc6出现一些令人难以理解的问题不必深究,对模板使用比较多的应用,多使用对c++98支持比较好的编译器较好,比如g++、vc71 above
#
re: 为什么在VS2005重载输出运算符那么难?
回复
更多评论
2006-03-17 11:07 by
jemmy
VC6 对C++标准支持不好,2003/2005却支持的很好
#
re: 为什么在VS2005重载输出运算符那么难?
回复
更多评论
2006-03-19 21:25 by
Ninputer
可以把export template放在CPP里,然后把template放到h里。不过这一特性还没有发现支持的编译器……
#
re: 为什么在VS2005重载输出运算符那么难?
回复
更多评论
2007-04-05 11:31 by
polyrandom
这个问题也可以用显式初始化解决。
如果你知道你将会在别的cpp里面用到Stack<int>,你可以在stack.cpp里面写:
template Stack<int>;
template ostream& operator <<(ostream& out,const SegStack<int>& seg);
不过你把operator<<写成friend可不是很好
#
re: 为什么在VS2005重载输出运算符那么难?
回复
更多评论
2009-05-23 23:00 by
yyf
如果一定要是类型绑定的,那怎么办呢?
刷新评论列表
只有注册用户
登录
后才能发表评论。
【推荐】100%开源!大型工业跨平台软件C++源码提供,建模,组态!
相关文章:
双链表模版类的实现
C风格字符串与标准库string类型性能对比
算法与数据结构实验(二)
为什么在VS2005重载输出运算符那么难?
我的算法与数据结构学习(三)
Josephus问题
算法与数据结构实验(一)
我的算法与数据结构学习(二)
我的算法与数据结构学习(一)
网站导航:
博客园
IT新闻
BlogJava
知识库
博问
管理
Powered by:
C++博客
Copyright © Tauruser
日历
<
2006年10月
>
日
一
二
三
四
五
六
24
25
26
27
28
29
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
公告
常用链接
我的随笔
我的评论
我参与的随笔
留言簿
(7)
给我留言
查看公开留言
查看私人留言
随笔分类
(16)
MFC(2)
计算机图形学(2)
密码学
数学模型
数值计算(2)
算法与数据结构(9)
信息论(1)
随笔档案
(34)
2007年3月 (1)
2007年2月 (2)
2007年1月 (1)
2006年10月 (1)
2006年6月 (3)
2006年5月 (5)
2006年4月 (6)
2006年3月 (14)
2006年2月 (1)
文章分类
(5)
密码学
数学模型
数值计算
算法与数据结构(4)
网络(1)
信息论
文章档案
(5)
2006年4月 (1)
2006年3月 (4)
相册
文章贴图
收藏夹
(3)
我的收藏(3)
协议
流媒体
中国协议网
友情链接
Orlaa
最新随笔
1. CListCtrl For Beginners(转载)
2. 结构体对齐的具体含义(#pragma pack) (转载)
3. MFC ComboBox 使用方法(转载)
4. 05年写的直线裁剪算法
5. C# Coding时的注释格式(zz)
6. 查找字符串的哈希方法(zz)
7. 木马客户端与服务端通讯如何隐藏不被发现
8. Gauss消去法直接求解方程组(附例程)
9. 使用AsycnSocket类进行简单双机通讯
10. Romberg求积(例程)
搜索
积分与排名
积分 - 104855
排名 - 237
最新评论
1. re: 双链表模版类的实现
问下:关于查找(search)那部分,我有点小问题要问,就是你直接就靠默认的比较操作符来比较,而你所用的是模版,链表支持各种类型,那么是字符串类型的链表或自定义类型的呢,你该怎么办
--周晓荣
2. re: OnSize()加入处理函数后,DEBUG报告出错
评论内容较长,点击标题查看
--NULL
3. re: C风格字符串与标准库string类型性能对比
评论内容较长,点击标题查看
--Hzj_jie
4. re: 05年写的直线裁剪算法
你这个算法也太复杂了吧
--啊啊啊啊啊啊
5. re: C++ Primer Fourth Edition (download file)
i want english edition
--zhccc
阅读排行榜
1. MFC ComboBox 使用方法(转载)(18703)
2. 结构体对齐的具体含义(#pragma pack) (转载)(11377)
3. Tab Control控件使用的例子(zz)(8343)
4. VC++2005 比 VC++ 6.0 退步了?(7511)
5. MAC地址有合法不合法之分吗?(7435)
评论排行榜
1. C风格字符串与标准库string类型性能对比(20)
2. VC++2005 比 VC++ 6.0 退步了?(12)
3. OnSize()加入处理函数后,DEBUG报告出错(8)
4. 为什么在VS2005重载输出运算符那么难?(7)
5. Gauss消去法直接求解方程组(附例程)(7)