【问题标题】:overload shift operator << to allow chaining重载移位运算符 << 以允许链接
【发布时间】:2013-07-22 08:22:45
【问题描述】:

我正在为运算符重载而苦苦挣扎,因为我希望它允许链接

class A{
 int a;
public:
 void doSomething(char *str);
 A operator<<(char *str);
}

所以我有这门课,我能做的就是拿一个字符串做一些事情,这对这个问题并不重要。

我现在能做的是

A *counter = new A();
counter->doSomething("hello");

如果我实现了重载的移位运算符

A A::operator<<(char *str)
{
  this->doSomething(str);
  return this;
}

我可以这样写

A *counter = new A();
(*counter) << "hello";

我希望我没有在这里犯错,因为现在我想知道如何允许链接

(*counter) << "hello" << "test";

我知道通过链接它会做到这一点

(*counter).operator<<("hello" << "test");

这显然没有任何意义,因为有两个字符串/字符数组 但我知道有办法做到这一点。我用谷歌搜索了它,但每个问题都只是关于将相同类型的实例链接在一起

然后我尝试将两个参数放入函数并将其添加为朋友...我不确定,但也许我必须使用char* 类型或流对象创建一个新的重载运算符并制作它作为A的朋友?

感谢您的帮助,我想应该有一个我现在看不到的简单答案。

【问题讨论】:

  • 您的运营商最好选择const char*

标签: c++ operator-overloading chaining


【解决方案1】:

你需要返回一个对*this的引用,所以你的返回类型需要是A&amp;

A& operator<<(char *str)
{
  this->doSomething(str); // as before
  return *this;           // return reference to this instance.
}

【讨论】:

  • 好吧,你可以按值返回并链式调用就好了。但是您可能想解释一下为什么您通常想要通过引用返回。
【解决方案2】:

我想澄清你的问题中有两个错误的假设。

  1. 当你想在指针上调用operator&lt;&lt; 时,你必须这样做 对于每个电话,不仅是第一个电话。这就是为什么

    A *counter = new A();
    (*counter) << "hello";
    

    有效,但是

    (*counter) << "hello" << "test";
    

    没有。第二个operator&lt;&lt; 将在指针上调用 由第一个返回,这不是您想要的。你必须写 (这很丑):

    (*((*counter) << "hello")) << "test";
    
  2. 移位运算符可以链接起来,然后从左到右求值 对,这就是为什么以下是另一个错误的假设:

    A << "hello" << "test";
    

    我知道通过链接它会做到这一点

    A.operator<<("hello" << "test");
    

    它实际上是这样评估的:

    A.operator<<("hello").operator<<("test");
    

    也就是说,更详细:

    ( A.operator<<("hello") ).operator<<("test");
    

如果operator&lt;&lt;返回的对象也可以链接操作符 实现operator&lt;&lt;,因此您可以返回*this 的副本 类型为A。但是,这会复制对象 不必要的,因为它很可能只会活得很 暂时且仅由以下操作员使用一次。

所以您要做的是在operator&lt;&lt; 中返回一个引用,在该引用上可以调用下一个operator&lt;&lt;。这避免了复制:

A& operator<<(char *str)
{
    this->doSomething(str);
    return *this;
}

返回一个指针是可能的,但不会产生你想要的,如上所述。语法会很丑。

【讨论】:

  • +1 - 很好的解释。回复“当你想在指针上调用 operator&lt;&lt; 时,你必须为每次调用都这样做,而不仅仅是第一次。” - 当operator&lt;&lt; 是会员时确实如此,但如果奇怪的话,非会员T* operator&lt;&lt;(T*, const char*) 也是可以想象的......
  • 是的,这是可能的,但确实很奇怪。我不建议为左侧的任何类型的指针重载运算符。只是因为它看起来很奇怪。
【解决方案3】:

operator &lt;&lt; 应该返回链接的引用。

A& operator<<(char *str);

A& A::operator<<(char *str)
{
  this->doSomething(str);
  return *this;
}

应该像这样使用

A counter;
counter << "hello" << "test";

【讨论】:

    【解决方案4】:
    A *counter = new A();
    

    使您的“计数器”成为指针,而不是对象。要在 A 上使用运算符,您可以使用

    (*counter) << "hello" 
    

    此外,我建议您重新考虑重载运算符。虽然一开始这似乎是一个很酷的想法,但它很容易导致代码难以理解和维护。

    【讨论】:

    • (*A) &lt;&lt; "hello" 应该是(*counter) &lt;&lt; "hello"
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-12
    • 1970-01-01
    • 1970-01-01
    • 2010-09-10
    • 1970-01-01
    相关资源
    最近更新 更多