2011-11-23 60 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