大家帮我看看一个操作符重载的问题
#include <fstream>
#include <iostream>
#include <complex>
using namespace std;
typedef complex<double> COMPLEX;
const double PI = 3.1415926;
const int PIAngle = 180;
static double MakeAngleFromRadian(double dRadian)
{
double dAngle = dRadian/PI*PIAngle;
if (dAngle<-PIAngle)
dAngle += 2*PIAngle;
else if (dAngle>PIAngle)
dAngle -= 2*PIAngle;
return dAngle;//返回值的范围在[-180,180]之间;
}
ostream& operator<<(ostream& os,const COMPLEX& cpValue)
{
os<<abs(cpValue)<<"∠"<<MakeAngleFromRadian(arg(cpValue));
return os;
}
void main()
{
COMPLEX cpxVale(0,0);
cout<<cpxVale<<endl;
ofstream outfile("d:\\temp\\rst.txt");
outfile<<cpxVale<<endl;
}
代码如上,我想实现幅值/相角的输出,但是我发现输出到控制台的是符合设计思路的,输出到文件中的是默认的复数的输出。请大侠赐教,多谢了!
问题点数:40、回复次数:5Top
1 楼mayflowers(黯然神伤)回复于 2005-08-04 22:47:48 得分 0
For class complex provides the common I/O operators << and >>:
template <class T, class charT, class traits>
std::basic_ostream<charT, traits>&
operator<< (std::basic_ostream<charT, traits>& strm, const std::complex<T>& c);
ostream and ofstream is defined in std as:
typedef basic_ostream<char> ostream;
typedef basic_ofstream<char> ofstream;
However, the basic_ofstream derives from basic_ostream, not ostream.
So the compiler regards ofstream as basibasic_ostream, not ostream.
When it sees "outfile<<cpxVale<<endl;", the "<<" provided by complex class will be called, while when it sees "cout<<cpxVale<<endl;", your function is better than std's.Top
2 楼mayflowers(黯然神伤)回复于 2005-08-04 22:56:27 得分 0
BTW:
ofstream& operator<<(ofstream& ofs, const COMPLEX& cpValue)
{
ofs << abs(cpValue) << "∠" << MakeAngleFromRadian( arg(cpValue) );
return ofs;
}
can bring you the right result.Top
3 楼fengchang(everate)回复于 2005-08-05 09:20:36 得分 0
typedef basic_ostream<char> ostream,不就是表明ostream是basic_ostream<char>的一个别名吗?Top
4 楼mayflowers(黯然神伤)回复于 2005-08-05 11:12:20 得分 39
非常抱歉,上面的回答是完全错误的。
而且在自己没有完全确定的时候回答这个问题更加不好。sorry。
According to C++ Primer 3rd P424 & P435:
函数模版推导四个步骤:
1. 生成候选参数集;
2. 生成可行参数集;
3. 对类型转换划分等级;
3.b. 如果调用是二义的,则从可行函数集中去掉函数模版实例;
4. 只考虑可行函数集中的普通函数。
在你的代码中,你的函数是一个普通函数(不是模版的特化)。
如你所说,这两个函数在3.b时是一样的(需要同样的类型转换),所以应该选择普通函数,也就是你的函数。
但是这个问题在VC 6.0中处理的非常怪异:
template <class T>
void func(T t)
{
}
void func(int i)
{
}
int main()
{
func((int) 1); // call func(int i);
func(0.0); // call template function;
return 0;
}
这一点是正确的,但是涉及到继承的时候,就会出现你的结果:
class A {}; class B : public A {};
void func(A a)
{
}
int main()
{
B b;
func(b); // call template function, not func(A a);
return 0;
}
这个不符合C++的规范——要求优先选择普通函数。
我在redhat下用g++3.2.2运行你的代码,可以得到你想要的结果。调用的是你的普通函数。
所以,如果没有疏漏的话,这个时vc的bug。
btw: 我的是vc6.0 + sp5。Top
5 楼fangrk(加把油,伙计!)回复于 2005-08-05 12:36:07 得分 1
.net2003编译通过,bcb6编译错误,标准库中已经有了complex的输出函数。
方法1:不要重载标准库中的输出函数
#include <fstream>
#include <iostream>
#include <complex>
using namespace std;
typedef complex<double> COMPLEX;
const double PI = 3.1415926;
const int PIAngle = 180;
static double MakeAngleFromRadian(double dRadian)
{
double dAngle = dRadian/PI*PIAngle;
if (dAngle<-PIAngle)
dAngle += 2*PIAngle;
else if (dAngle>PIAngle)
dAngle -= 2*PIAngle;
return dAngle;//返回值的范围在[-180,180]之间;
}
ostream& output(ostream& os,const COMPLEX& cpValue)
{
os<<abs(cpValue)<<"∠"<<MakeAngleFromRadian(arg(cpValue));
return os;
}
int main()
{
COMPLEX cpxVale(1,1);
ofstream outfile("a.txt");
output(cout,cpxVale);
output(outfile,cpxVale);
}
方法2:采用名字空间
#include <fstream>
#include <iostream>
#include <complex>
using namespace std;
namespace MyTest
{
typedef complex<double> COMPLEX;
const double PI = 3.1415926;
const int PIAngle = 180;
static double MakeAngleFromRadian(double dRadian)
{
double dAngle = dRadian/PI*PIAngle;
if (dAngle<-PIAngle)
dAngle += 2*PIAngle;
else if (dAngle>PIAngle)
dAngle -= 2*PIAngle;
return dAngle;//返回值的范围在[-180,180]之间;
}
ostream& operator<<(ostream& os,const COMPLEX& cpValue)
{
os<<abs(cpValue)<<"∠"<<MakeAngleFromRadian(arg(cpValue));
return os;
}
}
int main()
{
MyTest::COMPLEX cpxVale(1,1);
ofstream outfile("a.txt");
using MyTest::operator<<;//优先考虑MyTest中的输出函数
cout<<cpxVale;
outfile<<cpxVale;
}Top




