2011-11-23 31 views
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"; 

谢谢!

+0

[C++静态运算符重载]可能的重复(http://stackoverflow.com/questions/1390606/c-static-operator-overloading) – GWW

+4

我会说不,因为'MyClass' isn '值(它是*类型*),所以'MyClass <<“messa ge“'不是一个有效的表达式。你可以将MyClass :: msg'包装成一个'std :: istringstream',但是:'std :: istringstream(MyClass :: msg)<<“hello”<<“world”;' –

+0

@KerrekSB你的意思是std :: ostringstream,但我+1你的意见无论如何 – wreckgar23

回答

4

如果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"; 

然而,我不会推荐这样做。为什么不只是使用std::ostringstream?你会得到格式和更多的免费。如果您确实需要全局访问,请声明一个全局变量。

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++提供了具有类型参数的模板,不管怎样,它们都不会帮助您在类型上重载函数。

+0

即使类**中包含的内容是**值(_static_)? –

+0

@Pietro M:是的。 C++把它放在关键的地方,它没有将类型名作为普通参数传递给函数。 –

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"; 
1

如果你想使用你的类的清点,你可以做的是例如

#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