2012-03-02 96 views
1

謝謝你給意見如下。成員函數指針列表

Class1 { debug(std::ostream&){} }; 
int main() { 
    std::vector<Class1*> list1; 
    // some work to do 
} 

目標平臺:

  • 平臺(1):運7x64,VS2010
  • 平臺(2):Linux的32倍,克++ 4.4

問:將「std :: cout」傳遞給以下語句的正確方法是什麼?

std::for_each(list1.begin(), 
       list1.end(), 
       "afunction(&Class1::debug, std::cout)"); 

我以前使用的「性病::法院」調試()函數內部,但後來考慮到給靈活性調試信息的輸出。

編輯:更多信息:如果仿的對象是要走的路,應該怎麼實現函子,以應付多個類(這些類,除了有相同的「調試」函數簽名沒有關係)?

編輯(2):使用「的std :: for_each的」,是有可能通過調用相應的析構函數直接每個類摧毀list1的所有對象? (如的for_each(l.begin(),l.end(), 「類::〜1類」);

編輯(3):按照 「PMR」 的建議,我讓語句

std::for_each(l.begin(), 
       l.end(), 
       std::bind2nd(std::mem_fn(&Class1::debug), out)); 

它編譯和正確地在Linux平臺上運行,但未能在VS2010中,代碼的Class1 ::調試是

void Class1::debug(const std::ostream& out) 
{ 
    out << "some text" << someVar << "some text" << std::endl; 
} 

的VS錯誤味精是

錯誤C2678:二進制 '< <':沒有操作ATOR發現它接受一個左邊的操作數類型「常量性病的ostream ::」的(或不存在可接受的轉化率)

任何線索?

[已結算] 我現在爲我的類實現了重載運算符< <,並關閉了調試打印函數的使用。非常感謝所有提示。

回答

1

由於您使用的g ++ 4.4不能使用lambda表達式這將是第一選擇(更高版本支持他們,MSVC不一樣)。

所以你需要一個仿函數。函子是一個函數對象,它是實現operator()的類(或結構)。就像這樣:

class Debug 
{ 
public: 
    Debug(ostream& os) : _os(os) 
    { } 

    void operator()(Class1* instance) 
    { 
      // will print the pointer, replace with user code 
      os << instance << endl; 
    } 
private: 
    ostream& _os; 
}; 

使用這樣的:

Debug d(cout); 
std::for_each(list1.begin(), list1.end(), d); 
0

使用拉姆達而不是函數指針。這是C++ 11x的一個特性,您需要包含一個標誌讓編譯器識別lambda。

std::for_each(list1.begin(), list1.end(), [&debug, &cout] 
{ 
// implementaion 
} 
); 
0

由於GCC不支持lambda表達式,直到4.5,最明顯的解決方案是不可能的。

當你想使用很多通用算法的第二個最簡單的解決方法是Boost.Lambda http://www.boost.org/doc/libs/1_49_0/doc/html/lambda.html

for_each(list1.begin(), list.end(), _1->debug(cout)); 

最後,繁瑣的仿函數的解決方案:

class Output 
{ 
public: 
    explicit Output(ostream& ios) : os(&ios) 
    { 
    } 

    void operator()(Class1* obj) 
    { 
      obj->debug(*os); 
    } 

private: 
    ostream* os; 
}; 
for_each(list1.begin(), list1.end(), Output(cout)); 

我個人認爲,沒有C++ 11 lambdas或Boost Lambdas,for_each比它更值得痛苦。不妨做一個簡單的循環:

for (vector<Class1*>::iterator it = list1.begin(); it != end; ++it) 
    (*it)->debug(cout); 
0

C++ 03:

#include <vector> 
#include <functional> 
#include <iostream> 
#include <algorithm> 

struct Foo { 
    void debug(std::ostream&) {} 
}; 

int main() 
{ 
    std::vector<Foo*> foos; 
    std::for_each(foos.begin(), foos.end(), 
       std::bind2nd(std::mem_fun(&Foo::debug), std::cout)); 
    return 0; 
} 

請注意,粘合劑已被棄用,boost::bind或 C++ 11應該受到青睞。你應該真的得到一個更新的編譯器。

+0

我遵循你的建議,它編譯到一些點,但它在MS VS2010失敗,拋出錯誤「錯誤C2678:二進制'<<':找不到操作符,它需要類型爲'const std ::'的左操作數ostream'(或者沒有可接受的轉換)「 – 2012-03-05 03:03:18

+0

我在示例代碼中看不到任何'operator <<'。問題可能出在你輸出的方式上。不要''const''用'ostream',而用'&'代替。這應該解決它。 – pmr 2012-03-05 09:27:04