【问题标题】:why is this code not detecting << operator?为什么这段代码没有检测到 << 运算符?
【发布时间】:2021-08-20 02:32:11
【问题描述】:

请向我解释为什么这没有检测到 &lt;&lt; 运算符。

我尽了最大的努力,甚至尝试在两个类上重载&lt;&lt;(这不是必需的)。

#include<iostream>
using namespace std;

const int MAX = 10;

class Complex;

template<class t>
class stack {
private:
    t stk[MAX];
    int top;
public:
    stack() { top = -1; }
    void push(t data) {
        if (top == MAX - 1)
            cout << "Stack is full.";
        else
            stk[++top] = data;
    }

    t pop() {
        if (top == -1) {
            cout << "Stack is empty.";
            return NULL;
        }
        else {
            //return stk[top--];
            t data = stk[top];
            top--;
            return data;
        }
    }
};  

class Complex {
private:
    float real, imag;
public:
    Complex(float r = 0.0, float i = 0.0) { real = r; imag = i; }
    friend ostream& operator << (ostream& s, Complex& c);
};

ostream& operator << (ostream& s, Complex& c) {
    s << "(" << c.real << "," << c.imag << ")";
    return s;
}

int main() {
    stack<int> s1;
    s1.push(10);
    s1.push(20);
    s1.push(30);
    s1.push(40);
    cout << s1.pop() << endl;
    cout << s1.pop() << endl;
    cout << s1.pop() << endl;
    cout << s1.pop() << endl;

    stack<float> s2;
    s2.push(3.14f);
    s2.push(4.14f);
    s2.push(5.14f);
    s2.push(6.14f);
    cout << s2.pop() << endl;
    cout << s2.pop() << endl;
    cout << s2.pop() << endl;
    cout << s2.pop() << endl;

    Complex c1(1.5f, 2.5f), c2(1.5f, 2.5f), c3(1.5f, 2.5f), c4(1.5f, 2.5f);
    //cout<<c1;

    stack<Complex> s3;
    s3.push(c1);
    s3.push(c2);
    s3.push(c3);
    s3.push(c4);
    cout << s3.pop() << endl;
    cout << s3.pop() << endl;
    cout << s3.pop() << endl;
    cout << s3.pop() << endl;
    return 0;
}

【问题讨论】:

    标签: c++


    【解决方案1】:

    函数签名应该是这样的:

    std::ostream& operator<<(std::ostream& os, const T& obj)
    {
      // write obj to stream
    
      return os;
    }
    

    并且函数pop 不能返回NULL,因为类型与t 不同。固定代码可能喜欢:

    #include <iostream>
    using namespace std;
    
    const int MAX = 10;
    class Complex;
    template <class t>
    class stack {
     private:
      t stk[MAX];
      int top;
    
     public:
      stack() { top = -1; }
      void push(t data) {
        if (top == MAX - 1)
          cout << "Stack is full.";
        else
          stk[++top] = data;
      }
    
      t pop() {
        if (top == -1) {
          cout << "Stack is empty.";
          return {}; // May throw, or return std::optional here
        } else {
          // return stk[top--];
          t data = stk[top];
          top--;
          return data;
        }
      }
    };
    
    class Complex {
     private:
      float real, imag;
    
     public:
      Complex(float r = 0.0, float i = 0.0) {
        real = r;
        imag = i;
      }
      friend ostream &operator<<(ostream &s, const Complex &c);
    };
    
    ostream &operator<<(ostream &s, const Complex &c) {
      s << "(" << c.real << "," << c.imag << ")";
      return s;
    }
    
    int main() {
      stack<int> s1;
      s1.push(10);
      s1.push(20);
      s1.push(30);
      s1.push(40);
      cout << s1.pop() << endl;
      cout << s1.pop() << endl;
      cout << s1.pop() << endl;
      cout << s1.pop() << endl;
    
      stack<float> s2;
      s2.push(3.14f);
      s2.push(4.14f);
      s2.push(5.14f);
      s2.push(6.14f);
      cout << s2.pop() << endl;
      cout << s2.pop() << endl;
      cout << s2.pop() << endl;
      cout << s2.pop() << endl;
    
      Complex c1(1.5f, 2.5f), c2(1.5f, 2.5f), c3(1.5f, 2.5f), c4(1.5f, 2.5f);
      // cout<<c1;
    
      stack<Complex> s3;
      s3.push(c1);
      s3.push(c2);
      s3.push(c3);
      s3.push(c4);
      cout << s3.pop() << endl;
      cout << s3.pop() << endl;
      cout << s3.pop() << endl;
      cout << s3.pop() << endl;
      return 0;
    }
    

    Online demo.

    相关问题:What are the basic rules and idioms for operator overloading?

    【讨论】:

    • @vishnukumar 因为对于ostream&amp; operator &lt;&lt; (ostream &amp;s,Complex &amp;c){ 它期望第二个参数是l 值,但是对于pop 我们返回t pop(),我们不能在这里将非常量引用绑定到一个临时对象。请参阅此相关问题:stackoverflow.com/questions/59392050/…
    • 如果使用变量来存储pop的结果,那么我们就不需要将const Complex&amp;声明为参数
    【解决方案2】:

    它不起作用,因为第二个参数应该是const 引用

    class Complex{
        private:
            float real,imag;
        public:
            Complex(float r=0.0,float i=0.0){
                real=r;
                imag=i;
            }
            friend ostream& operator<<(ostream& s, const Complex& c);
    };
    
    ostream& operator<<(ostream& s, const Complex& c) {
        s<<"("<<c.real<<","<<c.imag<<")";
        return s;
    }
    

    【讨论】:

      【解决方案3】:

      原因: pop 函数返回一个右值。您可以将 r 值视为内存中的无名对象(当然,还有更多内容)。您不能将 r 值放入 l 值引用中。但是对于 const 引用,这并不重要,因为您不会修改它。

      解决方案 1:

      friend ostream &operator<<(ostream &s, Complex &c); // accepts lvalue - c refers to some external Complex object.
      
      friend ostream &operator<<(ostream &s, Complex &&c); // accepts rvalue - c becomes a normal local variable whose value is the passed rvalue.
      

      解决方案 2:

      friend ostream &operator<<(ostream &s, const Complex &c); // accepts both
      

      【讨论】:

        猜你喜欢
        • 2011-03-08
        • 2015-07-07
        • 2015-05-17
        • 2010-10-25
        • 2016-06-17
        • 1970-01-01
        • 1970-01-01
        • 2019-07-26
        • 2016-01-30
        相关资源
        最近更新 更多