【问题标题】:Invalid operands to binary expression ('std::ostream' (aka 'basic_ostream<char>') and 'sound_ctl')二进制表达式的无效操作数('std::ostream'(又名'basic_ostream<char>')和'sound_ctl')
【发布时间】:2021-09-09 23:18:04
【问题描述】:

我正在尝试编写 &lt;&lt; 运算符。我的代码:

#include <iostream>
#include <ostream>
class sound_ctl {
private:
    int _vol;
    bool _status;
public:
    sound_ctl() : _vol(50), _status(false) {};

    void operator++() {
        if (_vol <= 98) {
            _vol += 2;
        }
    }

    void operator--() {
        if (_vol >= 2) {
            _vol -= 2;
        }
    }

    void operator!() {
        _status = !_status;
    }

    std::ostream &operator<<(std::ostream &os) const {
        os << _status << "Volume: " + _vol << std::endl;
        return os;
    }

};


int main() {
    sound_ctl panel1;
    std::cout << panel1;
}

但是,代码不会编译错误:Invalid operands to binary expression ('std::ostream' (aka 'basic_ostream&lt;char&gt;') and 'sound_ctl')

我严重缺乏对 C++ 中的流的理解,因此,了解潜在问题会对我有很大帮助。谢谢

【问题讨论】:

    标签: c++ stream


    【解决方案1】:

    您不应将输入/输出运算符定义为成员函数。

    std::ostream &operator<<(std::ostream &os, const sound_ctl& sc) {
        os << sc._status << "Volume: " + sc._vol << std::endl;
        return os;
    }
    

    然后将该函数声明为友元:

    class sound_ctl {
    friend std::ostream &operator<<(std::ostream &os, const sound_ctl& sc);
    // ...
    };
    

    你为什么不能像std::cout &lt;&lt; panel1那样调用输出?因为您可以看到&lt;&lt; 只是operator&lt;&lt;() 函数的函数调用的语法糖。如果此函数是成员函数,则左侧将作为隐式this 传递,而右侧将是参数列表中的参数。意味着您必须像这样调用输出:

    panel1 << std::cout; // No comments...
    

    我们通过将类的对象作为显式的第二个参数传递给我们的操作符来避免这种情况:ostream&amp; operator&lt;&lt;(ostream&amp;, const sound_ctl&amp;)

    您可能想查看此thread。这也会有所帮助:Overloading The IO Operators

    另外,请注意,在重载运算符中模仿内置运算符 是一种很好的做法。因此,您的 operator++ 应该返回对调用它的对象的引用。如果你定义了一个前缀,你应该还定义一个后缀递增/递减运算符。

    【讨论】:

    • 谢谢!不过,为什么我不应该将它们声明为成员函数呢?
    • @Omri.B 总结一下:对于任何对象o,那么o &lt;&lt; xo.operator&lt;&lt;(x) 相同(如果operator&lt;&lt; 是成员函数) .或operator&lt;&lt;(o, x)(如果operator&lt;&lt; 不是成员函数)。对于所有可以重载的运算符,这个一般的经验法则都是相同的。
    • @Omri.B 检查最新编辑。添加了对已经涵盖所有内容的地方的引用。
    【解决方案2】:

    您的所有运算符都未正确实施。见What are the basic rules and idioms for operator overloading?

    但是,具体到operator&lt;&lt;,它不能作为类的成员来实现,它必须是一个独立的函数。它需要两个参数,写入的流和写入的对象。

    试试这个。

    #include <iostream>
    #include <ostream>
    
    class sound_ctl {
    private:
        int _vol;
        bool _status;
    public:
        sound_ctl() : _vol(50), _status(false) {};
    
        sound_ctl& operator++() {
            if (_vol <= 98) {
                _vol += 2;
            }
            return *this;
        }
    
        sound_ctl operator++(int) {
            sound_ctl tmp(*this);
            ++(*this);
            return tmp;
        }
    
        sount_ctl& operator--() {
            if (_vol >= 2) {
                _vol -= 2;
            }
            return *this;
        }
    
    
        sound_ctl operator--(int) {
            sound_ctl tmp(*this);
            --(*this);
            return tmp;
        }
    
        bool operator!() const {
            return !_status;
        }
    
        // even though this is inlined within the class declaration,
        // it is NOT actually a member of the class!
        friend std::ostream& operator<<(std::ostream &os, const sound_ctl& ctl) {
            os << ctl._status << " Volume: " + ctl._vol << std::endl;
            return os;
        }
    };
    
    int main() {
        sound_ctl panel1;
        std::cout << panel1;
    }
    

    或者,如果你真的想使用成员方法:

    #include <iostream>
    #include <ostream>
    
    class sound_ctl {
    private:
        int _vol;
        bool _status;
    public:
        sound_ctl() : _vol(50), _status(false) {};
    
        sound_ctl& operator++() {
            if (_vol <= 98) {
                _vol += 2;
            }
            return *this;
        }
    
        sound_ctl operator++(int) {
            sound_ctl tmp(*this);
            ++(*this);
            return tmp;
        }
    
        sount_ctl& operator--() {
            if (_vol >= 2) {
                _vol -= 2;
            }
            return *this;
        }
    
    
        sound_ctl operator--(int) {
            sound_ctl tmp(*this);
            --(*this);
            return tmp;
        }
    
        bool operator!() const {
            return !_status;
        }
    
        void print(std::ostream &os) const {
            os << _status << " Volume: " + _vol << std::endl;
        }
    };
    
    std::ostream& operator<<(std::ostream &os, const sound_ctl& ctl) {
        ctl.print(os);
        return os;
    }
    
    int main() {
        sound_ctl panel1;
        std::cout << panel1;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-05-08
      • 2019-07-10
      • 2017-03-12
      • 1970-01-01
      • 1970-01-01
      • 2021-08-20
      • 1970-01-01
      相关资源
      最近更新 更多