可以为算术表达式重载ostream运算符吗?

时间:2013-11-15 13:02:59

标签: c++ operator-overloading ostream

是否可以为执行算术运算的ostream运算符创建重载(例如,添加),然后流出结果?可以在整个Web上找到的标准ostream重载只能从单个变量中流式传输。我需要做以下事情:

std::cout << x+y << std::endl;

或甚至更复杂的表达式,如:

std::cout << x*y+(3*z)^2 << std::endl;

其中x,y和z是一个简单的定制结构的实例,其中已经定义了算术运算(重载)。

修改

这是我的代码:

struct scalar //complex scalar data structure
{
friend scalar operator^(const scalar&, int); //integer power operator overload
friend scalar exp(const scalar&); //exponential power function
std::ostream& operator<<(std::ostream&, const scalar&)
protected:
  double re;
  double im;
public:
  double real() {return re;} //returns the real part
  double imag() {return im;} //returns the imaginary part
  scalar(double _re, double _im) {re=_re;im=_im;} //constructor 1
  scalar(double _re) {re=_re;im=0.0;} //constructor 2
  scalar(const scalar& s): re(s.re), im(s.im) {} //copy constructor
  scalar& operator=(const scalar& rhs) //assignment operator overload
  {
    if (&rhs==this) return *this; //checks for self-assignment
    re=rhs.re; //sets real parts equal
    im=rhs.im; //sets imaginary parts equal
    return *this;
  }
  scalar& operator+=(const scalar& rhs) //compound addition-assignment operator overload
  {
    if (&rhs==this) return *this; //checks for self-assignment
    re=re+rhs.re; //adds real parts
    im=im+rhs.im; //adds imaginary parts
    return *this;
  }
  scalar& operator*=(const scalar& rhs) //compound multiplication-assignment operator overload
  {
    if (&rhs==this) return *this; //checks for self-assignment
    double x1=re; double x2=rhs.re; double y1=im; double y2=rhs.im;
    re=x1*x2-y1*y2; //multiplies real parts
    im=x1*y2+x2*y1; //multiplies imaginary parts
    return *this;
  }
  scalar& operator-=(const scalar& rhs) //compound subtraction-assignment operator overload
  {
    if (&rhs==this) return *this; //checks for self-assignment
    re=re-rhs.re; //adds real parts
    im=im-rhs.im; //adds imaginary parts
    return *this;
  }
  scalar& operator/=(const scalar& rhs) //compound division-assignment operator overload
  {
    if (&rhs==this) return *this; //checks for self-assignment
    double x1=re; double x2=rhs.re; double y1=im; double y2=rhs.im;
    double n;
    n =pow(x2,2)+pow(y2,2);
    if (n==0) throw(1);
    re=(x1*x2+y1*y2)/n; //multiplies real parts
    im=(x2*y1-x1*y2)/n; //multiplies imaginary parts
    return *this;
  }
  const scalar operator+(const scalar& b) //addition operator overload
  {
    scalar c = *this;
    c+=b;
    return c;
  }
  const scalar operator*(const scalar& b) //addition operator overload
  {
    scalar c = *this;
    c*=b;
    return c;
  }
  const scalar operator-(const scalar& b) //addition operator overload
  {
    scalar c = *this;
    c-=b;
    return c;
  }
  const scalar operator/(const scalar& b) //addition operator overload
  {
    scalar c = *this;
    c/=b;
    return c;
  }
};

scalar i(0.0,1.0);
scalar j(0.0,1.0);

std::ostream& operator<<(std::ostream& out, const scalar& s)
{
  out << s.re << '+' << s.im << 'i';
  return out;
}

scalar operator^(scalar a, int b) //integer power operator overload
{
  double x=a.real(); double y=a.imag();
  if (x==0) throw(1);
  int r=sqrt(pow(x,2)+pow(y,2));
  int arg=atan2(y,x);
  scalar c(r*cos(arg),r*sin(arg));
  return c;
}

scalar exp(const scalar& s) //exponential power function
{
  double x=s.re; double y=s.im;
  scalar c(exp(x)*cos(y),exp(x)*sin(y));
  return c;
}

这是我的主要功能:

int main()
{
  scalar x(3,4);
  scalar y=2;
  cout << x*y << endl;
  return 0;
}

这是它应该给出的输出:

6+8i

这就是它给出的错误:

In function 'std::ostream& operator<<(std::ostream&, const scalar&)':|
error: passing 'const scalar' as 'this' argument of 'double scalar::real()' 
discards qualifiers|

如果我按照编译器的说法删除const,我将收到以下错误:

error: no match for 'operator<<' in 'std::cout << scalar::operator*(const scalar&)
(((const scalar&)((const scalar*)(& y))))'|

4 个答案:

答案 0 :(得分:3)

<<运算符无法处理完整表达式 - 为什么要这样?

您需要为结构实现单独的运算符(operator +,operator *,...),它将结构作为参数,对其执行相应的操作,并返回另一个结构。只有然后定义一个operator<<只接受你的一个结构。

你怎么会想到将这样一个复杂的结构传递给运算符&lt;&lt;,更不用说在那里解析了?实现单独的运算符,并将解析保留给编译器。

e.g。对于仅封装int的简单结构,使用+操作执行此操作将如下所示:

struct mystruct
{
     int value;
};

然后定义:

mystruct const operator+(mystruct const & a, mystruct const & b)
{
    mystruct result;
    result.value = a.value + b.value;
    return result;
}

std::ostream & operator<<(std::ostream& out, mystruct const & a)
{
    out << a.value;
    return out;
}

然后你可以这样做:

mystruct a, b;
a.value = 1;
b.value = 2;
std::cout << a+b;

修改:使用更新的代码,只有一个问题:

std::ostream& operator<<(std::ostream&, const scalar&)

应该是

friend std::ostream& operator<<(std::ostream&, const scalar&);

即。您遗漏了friend;

虽然您显示的错误表明存在一些不同的问题(jrok的答案会有解决方案) - 这似乎不是编译您显示的代码所致!因此,请同步显示所显示的代码和错误消息。

答案 1 :(得分:2)

你为什么不写std::cout << (x+y) << std::endl;
并完成?

答案 2 :(得分:2)

错误是因为函数scalar::realscalar::imag不是const - 当您获得对常量{const的引用时,您只能调用scalar成员函数1}}。

   double real() const {return re;}
   double imag() const {return im;}

答案 3 :(得分:1)

只要您的重载运算符按值获取其参数:

ostream& operator<<(ostream&, Thing)

或不断引用:

ostream& operator<<(ostream&, const Thing&)

您可以将其用于Thing类型的任何表达式。

您应该在复杂表达式周围加上括号,以避免出现运算符优先级的意外情况;特别是,涉及^的第二个表达式将不会按预期进行解析。

如果运算符需要非常量引用,则只限于单个变量(或更准确地说,左值表达式);所以不要这样做。

UPDATE 现在我们已经看到了代码,主要问题是operator<<作为成员函数的类内定义;它不能成为会员。也许您希望它是friend,因此它可以访问imre;或者你应该删除声明(使其成为非成员,非朋友),并使用公共接口。如果您这样做,则需要将const添加到real()imag(),以便可以在const对象上调用它们。无论如何你应该这样做。

(查看报告的错误,您似乎已经将其更改为使用公共接口,但尚未声明必要的函数const)。