重载运算符<<更改成员变量

overloading operator<< to change member variable

本文关键字:lt 成员 变量 重载 运算符      更新时间:2023-10-16

我有一个类,看起来像这样:

class A {
  public:
    A() {};
    A& operator<< (A& a, unsigned int i);
  private:
    vector<int> abc;
}

我想提供使用操作符向abc添加对象的能力:

A a();
a << 3,4,5; // should do the same as several calls of abc.push_back(i)

我知道我必须重载<<运算符,我是否也必须重载,运算符?

实际的方法是什么样子的?

永远不要重载c++中的,操作符。语言允许这样做,但您不能在这样做的同时保留操作符的预期行为。(特别是,逗号操作符在c++中是一个序列点:编译器保证左表达式在右表达式之前求值。如果重载它,将不再保证哪个表达式将首先求值。

你想使用流插入操作符的多次调用来插入多个对象。

(为了完整起见:你永远不应该重载的另外两个c++操作符是&&||。同样,不可能提供客户端代码所期望的行为(在这种情况下是短路)。

如果您想保留a << 1, 2, 3的方面,您可以更改operator<<的重载以接受intinitializer_list,而不是单个int

#include <initializer_list>
class A {
    public:
    A() {};
    A& operator<< (std::initializer_list<int> values);
    private:
    vector<int> abc;
}

然后实现如下:

A& A::operator<< (std::initializer_list<int> values)
{
    for(const auto& value : values)
        abc.push_back(value);
    return *this;
}

并按如下方式使用:

A a;
a << {1, 2, 3, 4};

你唯一需要确保的是你有一个兼容c++ 11的编译器来提供这些特性

Eigen库实现了这种语法。我不确定你是不是从那里来的

Eigen是一个表达式模板库。它定义了操作符和函数,这些操作符和函数看起来可以做一些事情,但实际上只是代理对象的工厂。代理形成编译时,有时是运行时数据结构,决定何时以及如何进行计算。

要实现这种语法,需要代理对象。把它比作std::ostreama << 3返回一个代理"流"对象,然后重载operator ,以启用, 4, 5部分。代理也可以重载operator<<,在这种情况下,语法将是a << 3 << 4 << 5。这可能更简洁,但Eigen是一个数学和操作符重载密集型库,,作为最低优先级的操作符有一个特殊的位置,这减少了a << 3, true? 4 : 42, 5这样的初始化中出现优先级错误的可能性。

长话短说,即使你这样做,你也应该坚持只使用operator<<

class A {
  public:
    A() {};
    inserter operator << (A& a, unsigned int i) {
      inserter ret( * this );
      ret , i;
      return ret;
    }
  private:
    vector<int> abc;
    struct inserter {
      A &client;
      inserter( A &in_client ) : client( in_client ) {}
      inserter &operator , ( int x ) {
        client.abc.push_back( x );
        return this;
      }
    };
    friend struct inserter;
};