请教(有关模板 操作符重载)
请看这样一段代码:
#include <iostream>
using namespace std;
class Date
{
int mo, da, yr;
public:
Date( int m, int d, int y )
{
mo = m; da = d; yr = y;
}
friend ostream& operator<< ( ostream& os, Date& dt );
};
ostream& operator<< ( ostream& os, Date& dt )
{
os << dt.mo << '/' << dt.da << '/' << dt.yr;
return os;
}
void main()
{
Date dt( 5, 6, 92 );
cout << dt;
}
很简单吧,编译通过,运行没有问题
结果为:5/6/92
但我将上面的代码稍做修改,加入模板定义,问题就来了
#include <iostream>
using namespace std;
template <class type>
class Date
{
public:
Date( type m, type d, type y )
{
mo = m; da = d; yr = y;
}
friend ostream& operator<< ( ostream& os, Date<type>& dt );
private:
type mo, da, yr;
};
template <class type>
ostream& operator<< ( ostream& os, Date<type>& dt )
{
os << dt.mo << '/' << dt.da << '/' << dt.yr;
return os;
}
void main()
{
Date<int> dt( 5, 6, 92 );
cout << dt;
}
编译时一样没有错误,但运行时产生一个错误:
C++ error LNK2019: unresolved external symbol "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl operator<<(class std::basic_ostream<char,struct std::char_traits<char> > &,class Date<int> &)" (??6@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@AAV?$Date@H@@@Z) referenced in function _main
我查了MSDN,上面说这个错误一般是由于所要调用的函数,或者引用的参数只声明未定义造成的。可上面我修改后的代码并没有这些问题,百思不得其解,还请各位高人指点!
多谢!!
问题点数:0、回复次数:11Top
1 楼freewing(羽田共)回复于 2003-08-01 01:26:12 得分 0
用什么编译的?
这是你上面的代码在VC6下的结果
I:\aaa.cpp(21) : error C2248: 'mo' : cannot access private member declared in class 'Date<int>'
I:\aaa.cpp(15) : see declaration of 'mo'
I:\aaa.cpp(28) : see reference to function template instantiation 'class std::basic_ostream<char,struct std::char_traits<char> > &__cdecl operator <<(class std::basic_ostream<char,struct std::char_traits<char> > &,class Date<int> &)' being c
ompiled
I:\aaa.cpp(21) : error C2248: 'da' : cannot access private member declared in class 'Date<int>'
I:\aaa.cpp(15) : see declaration of 'da'
I:\aaa.cpp(28) : see reference to function template instantiation 'class std::basic_ostream<char,struct std::char_traits<char> > &__cdecl operator <<(class std::basic_ostream<char,struct std::char_traits<char> > &,class Date<int> &)' being c
ompiled
I:\aaa.cpp(21) : error C2248: 'yr' : cannot access private member declared in class 'Date<int>'
I:\aaa.cpp(15) : see declaration of 'yr'
I:\aaa.cpp(28) : see reference to function template instantiation 'class std::basic_ostream<char,struct std::char_traits<char> > &__cdecl operator <<(class std::basic_ostream<char,struct std::char_traits<char> > &,class Date<int> &)' being c
ompiled
Error executing cl.exe.
aaa.exe - 3 error(s), 0 warning(s)
把
private:
type mo, da, yr;
改成
public:
type mo, da, yr;
通过
Top
2 楼sworddish(疯狂的君子兰)回复于 2003-08-01 01:38:29 得分 0
我使用的是.net 2003,这跟private或者public没关系,只要声明为右元就可以访问类中的私有成员Top
3 楼freewing(羽田共)回复于 2003-08-01 02:13:37 得分 0
friend我认识,不过事实在上面,要不就把
#include <iostream>
using namespace std;
改成
#include "iostream.h"
我想也可以通过,这你得找namespace stdTop
4 楼sworddish(疯狂的君子兰)回复于 2003-08-01 02:16:29 得分 0
问题已解决,可不知为什么?
将在全局域中定义的重载操作符移至类内定义就可正常运行,但我觉得从语法角度来说,这一改变等于什么也没做。
#include <iostream>
using namespace std;
template <class type>
class Date
{
public:
Date( type m, type d, type y )
{
mo = m; da = d; yr = y;
}
friend ostream& operator<< ( ostream& os, Date<type>& dt )
{
os << dt.mo << '/' << dt.da << '/' << dt.yr;
return os;
}
private:
type mo, da, yr;
};
void main()
{
Date<int> dt( 5, 6, 92 );
cout << dt;
}
Top
5 楼chengsion()回复于 2003-08-01 06:53:52 得分 0
是这样的,你的模板定义是对类Class Date中的Data Member 和 Function Member起作用,而友元函数是不属于Date的,故会有这样的情况。Top
6 楼mechgoukiteng(变态是一种生活态度)回复于 2003-08-01 09:11:27 得分 0
关于friend和tenplate的麻烦很多的
特别是如果你的class template在一个namespace中
推荐去newsgroup看一下Top
7 楼feixue3000(happy3001)回复于 2003-08-01 09:41:29 得分 0
VC对标准C++的支持不太好,建议你安装VC的PACK包,我装到PACK4,按第一个编译完全没有错误,你可以到linux下用GCC对第一个程序编译一下,我估计就没有问题,GCC对ANSI C++支持较好,而且支持SGI STL。Top
8 楼eric8231(1328cire)回复于 2003-08-01 18:52:19 得分 0
将原程序中 friend ostream& operator<< ( ostream& os, Date<type>& dt );
改为: friend ostream& operator<< <>( ostream& os, Date<type>& dt );
Top
9 楼eric8231(1328cire)回复于 2003-08-01 18:59:44 得分 0
在这里,friend函数的名字后面必须加“<>”以提示编译器这个friend函数是模板函数。
否则编译器会假定它是非friend函数。Top
10 楼williamVII(spread)回复于 2003-08-04 14:19:17 得分 0
偶汗,
偶用的也是NET,
把楼主的两份代码贴上去,
运行一点问题也没有,
汗呀。。。。
Top
11 楼nilm()回复于 2003-08-04 17:48:53 得分 0
在vc7.0上可以通过。
估计在friend 前面加 template<>就行了,告诉它这是个模板函数。让编译器给我们写程序是很麻烦的事情。Top



