【问题标题】:Member function to a list of pointer指针列表的成员函数
【发布时间】:2012-03-02 09:29:38
【问题描述】:

感谢您为以下提供 cmets。

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

目标平台:

  • 平台(1):Win 7x64,VS2010
  • 平台(2):Linux x32,g++ 4.4

问:将“std::cout”传递给以下语句的正确方法应该是什么?

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

我之前在 debug() 函数中使用了“std::cout”,但后来考虑为调试消息的输出提供灵活性。

编辑:更多信息:如果函子对象是要走的路,我应该如何实现函子来处理多个类(这些类除了相同的“调试”函数签名之外没有关系)?

Edit(2):使用“std::for_each”,是否可以通过直接为每个类调用相应的析构函数来销毁 list1 中的所有对象? (例如 for_each(l.begin(), l.end(), "Class::~Class1");

Edit(3):根据“pmr”的建议,我将声明设为

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

在linux平台编译运行正常,VS2010编译失败,Class1::debug代码为

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

VS 错误消息是

错误 C2678: 二进制 '

有什么提示吗?

[关闭] 我现在为我的类实现了重载运算符

【问题讨论】:

    标签: c++ foreach member-function-pointers


    【解决方案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);
    

    【讨论】:

      【解决方案2】:

      使用 lambda 代替函数指针。这是 C++11x 的一个特性,您需要包含一个标志以便编译器识别 lambda。

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

      【讨论】:

        【解决方案3】:

        由于 GCC 直到 4.5 才支持 lambda,所以最清晰的解决方案是不可能的。

        当您想使用大量通用算法时,第二个最简单的解决方案是 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);
        

        【讨论】:

          【解决方案4】:

          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 应该受到青睐。你真的应该得到一个更新的编译器。

          【讨论】:

          • 我按照您的建议进行了编译,但它在 MS VS2010 上失败了,抛出错误“错误 C2678: binary '
          • 我在示例代码中看不到任何operator&lt;&lt;。问题可能出在您的输出方式上。不要将ostream 替换为const&amp; 而是&amp;。这应该可以解决它。
          猜你喜欢
          • 2011-04-12
          • 2011-04-29
          • 1970-01-01
          • 1970-01-01
          • 2018-09-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多