4

是否可以定义一个仅对类的静态成员进行操作的静态插入运算符?就像是:

class MyClass
{
public:
    static std::string msg;

    static MyClass& operator<< (const std::string& token) {
        msg.append(token);
        return *this;   // error, static
    }
};

或者:

static MyClass& operator<< (MyClass&, const std::string &token)
{
    MyClass::msg.append(token);
    return ?;
}

这就是我想使用它的方式:

MyClass << "message1" << "message2";

谢谢!


你不能。类名/类型本身不是一个值,您需要一个类似的表达式

class Foobar {...};

std::cout << Foobar << std::endl;

这样你的静态operator<<就可以使用了,但这不是有效的 C++。A.4 的语法摘要表明,将类型名称放在那里是无效的。

还要考虑运算符重载只是具有易碎名称的函数:

T  operator<< (T, T)
   ^^^^^^^^^^ flaky name, basically same as:
T  left_shift (T, T)

C++(以及大多数其他语言,例如 C#)中的函数只能作用于类型的实例,而不能作用于类型本身。

但是,C++ 提供了具有类型参数的模板,但是,这并不能帮助您在类型上重载函数。

4

4 回答 4

10

在您的情况下,我可能会做的是创建另一个重载 的类operator<<,然后创建该类型的静态成员。像这样:

class MyClass
{
public:
    static std::string msg;

    struct Out {
        Out & operator<< (const std::string& token) {
            MyClass::msg.append(token);
            return *this;
        }
    };

    static Out out;    
};

使用它并不完全符合您的要求,但我认为足够接近:

MyClass::out << "message1" << "message2";
于 2011-11-23T17:44:52.517 回答
3

如果 的所有成员MyClass都是静态的,则可以返回一个新实例。

但是,返回引用会带来问题。有两种解决方案:

  • 定义一个静态实例
  • 通过副本传递,而不是通过引用传递。

第二种方法最简单:

static MyClass operator<< (MyClass, const std::string &token)
{
     MyClass::msg.append(token);
     return MyClass();
}

第一个是多行:

static MyClass& operator<< (MyClass&, const std::string &token)
{
     static MyClass instance;

     MyClass::msg.append(token);
     return instance;
}

用法非常接近您想要的:

MyClass() << "message1" << "message2";

但是,我不建议这样做。你为什么不直接使用 a std::ostringstream?您将免费获得格式和更多内容。如果你真的需要全局访问,声明一个全局变量。

于 2011-11-23T17:46:25.167 回答
1

如果您想将您的课程用作 cout,您可以做的就是示例

#include <iostream>
using namespace std;
namespace trace
{
  class trace
  {
  public:
    trace& operator<< (const std::string& echo)
    {
      std::cout << echo << std::endl;
      return *this;
    }
  };

  trace t; // Note that we created variable so we could use it.
};

using namespace trace; // Note that we use same namespace so we dont need to do trace::t
int main(int argv, char** argc)
{
  t << "Server started..."
    << "To exit press CTRL + Z";
  return 0;
}

输出应该看起来像新行中的每个字符串,如下所示:

服务器已启动...要退出,请按 CTRL + Z

于 2012-10-10T21:54:08.683 回答
0

你不能。类名/类型本身不是一个值,您需要一个类似的表达式

class Foobar {...};

std::cout << Foobar << std::endl;

这样你的静态operator<<就可以使用了,但这不是有效的 C++。A.4 的语法摘要表明,将类型名称放在那里是无效的。

还要考虑运算符重载只是具有易碎名称的函数:

T  operator<< (T, T)
   ^^^^^^^^^^ flaky name, basically same as:
T  left_shift (T, T)

C++(以及大多数其他语言,例如 C#)中的函数只能作用于类型的实例,而不能作用于类型本身。

但是,C++ 提供了具有类型参数的模板,但是,这并不能帮助您在类型上重载函数。

于 2011-11-23T17:40:26.657 回答