2015-06-21 61 views
1

我使用一个包装类各地std::thread,它是使用计时器结构(基于boost::asio)一些代码,调用methodToCallEachIteration()每5000毫秒:C++ lambda,没有看到函数和参数?

class OurThreadWrapperClass{ 
    OurThreadWrapperClass(boost::asio::io_service& = generic_timer_queue_s()); 
}; 

class A { 
    A() : thread1(_TimerIOService){ 
     thread1.setInterval(5000); 
     // This sets the callback function, to be called every INTERVAL ms. 
     thread1.start([this](OurThreadWrapperClass&) { 
      this->methodToCallEachIteration(); 
     }); 
    } 

    void callAFunctionHere(std::bitset<10> arg) { 
     // ... 
    } 

    void methodToCallEachIteration() { 
     // ... 
    } 

    struct TimerService { 
     constexpr static const size_t num_threads{2}; 

     TimerService(){ 
      for(auto& t: _threads){ 
       t = std::thread([this](){ 
        boost::asio::io_service::work keepalive{_ioservice}; 

        callAFunctionHere(_anArgument); // The method and arg not recognised 

        (void)keepalive; 
        _ioservice.run(); 
       }); 
      } 
     } 

     operator boost::asio::io_service&() { 
      return _ioservice; 
     } 

     boost::asio::io_service _ioservice{num_threads}; 
     std::thread _threads[num_threads]; 
    }; 

    OurThreadWrapperClass thread1; 
    TimerService _TimerIOService; 
    std::bitset<10> _anArgument; 
}; 

我遇到的问题是,我想从准备线程的TimerService中调用callAFunctionHere()。我无法在TimerService中移动此函数。然而,编译器抱怨说,它无法找到callAFunctionHere()_anArgument

error: cannot call member function callAFunctionHere(std::bitset<10>) without object 

error: 'std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = TimerService::TimerService()::__lambda19; _Args = {}]', declared using local type TimerService::TimerService()::__lambda19', is used but never defined [-fpermissive] 
     thread(_Callable&& __f, _Args&&... __args) 

我想我需要改变A::A()拉姆达这样编译器可以“看到”的方法和说法,但我不太知道如何?

+0

[如何对指到封闭实例-from-c-inner-class](http://stackoverflow.com/questions/6198224/how-to-refer-to-enclosing-instance-from-c-inner-class) –

+0

你可能想重新考虑你的封装这里。 “A”和“TimerService”的功能似乎很混乱,如果意图是为了使TimerService中的功能可以在其他类中重用,而不是使它成为嵌套类“A”,那么似乎是多余的。 – kfsone

+0

BTW'thread1'是在'_TimerIOService'之前构建的,因此您将未初始化的对象传递给'thread1'的构​​造函数。 – Oktalist

回答

0

在正在调用callAFunctionHere拉姆达,所捕获的this是一个为class A::TimerService的实例,但试图暗中使用class A实例的成员。您需要对A类型的对象的引用,并使用该对象的成员。

class A { 
    A() : _TimerIOService(this), thread1(_TimerIOService){ 
     //... 
    } 
    //... 
    struct TimerService { 
     A *a_; 
     constexpr static const size_t num_threads{2}; 

     TimerService(A *a) : a_(a) { 
      //... 
    //... 
    TimerService _TimerIOService; 
    OurThreadWrapperClass thread1; 
    std::bitset<10> _anArgument; 
}; 

注意_TimerIOService需要thread1面前。 现在,A::TimerService中的lambda使用a_来访问所需的成员。

+0

嗨,是不是在A ctor的lambda调用期间传入的A对象?这[位]? – user997112

+0

'this'与TimerService中的'this'无关。 – so61pi

+0

'class A'和'class A :: TimerService'是两种不同的类型,并且彼此之间没有任何隐式关系。在'A'里面定义'TimerService'只是简单的定义类名。内部类的内部实例没有任何访问定义类的包含类的概念。 – jxh

1

与往常一样,下破该问题的MVCE:

class A { 
    void callAFunctionHere() {} 

    struct TimerService { 
     TimerService() { 
      callAFunctionHere(); 
     } 
    }; 
}; 

int main() 
{ 
    A a; 
    A::TimerService ts; 
} 

http://ideone.com/lEUCvO

prog.cpp: In constructor 'A::TimerService::TimerService()': 
prog.cpp:6:35: error: cannot call member function 'void A::callAFunctionHere()' without object 
      callAFunctionHere(); 

此特定错误是告诉你的是,由于名称解析,编译器可以告诉你”重新尝试访问外部作用域(class A)的函数/成员,但是您正在从内部(class A::TimerService)的实例的上下文中执行此操作。

这行代码:

callAFunctionHere(_anArgument); 

在内部A::TimerService::TimerService()写入,所以this指针是(A::TimerService*) this和代码扩展为:

A::callAFunctionHere(A::_anArgument); 

this不能应用于其中的任一的,因为AA::TimerService之间没有直接继承或转换。

的类是嵌套的命名的目的,像namespace,但他们在其他方面的离散:只是因为TimerService宣布A内部没有他们的情况下连接名称作用域之外:它不建立一个继承或转换关系

也许是你所要做的是创建一个通用TimerService类可以通过继承来形容可重复使用的功能:

#include <iostream> 

struct TimerService 
{ 
    virtual void handleTimerEvent() = 0; 

    TimerService() 
    { 
    } 

    void trigger() 
    { 
     handleTimerEvent(); 
    } 
}; 

class A : public TimerService 
{ 

    const char* m_name; 

public: 
    A(const char* name_) : TimerService(), m_name(name_) {} 

    void handleTimerEvent() override 
    { 
     std::cout << "Handling timer event in " << m_name << '\n'; 
    } 
}; 

void triggerEvent(TimerService& service) 
{ 
    service.trigger(); 
} 

int main() 
{ 
    A a("A instance 'a'"), b("A instance 'b'"); 
    triggerEvent(b); 
    triggerEvent(a); 
} 

http://ideone.com/92aszw

+0

嗨,是否有解决上述代码的方法,以便TimerService可以持有指向A的指针? – user997112

+0

你可以但它没有多大意义。在上面的例子中,'A'的一个实例是'TimerService'的一个实例,带有额外的'A'特定的事物。所以你不需要一个指向'A'的指针,只需使用'virtual'函数来调用'TimerService'不应该提供的任何东西,并且它们在'A'中实现它们。现在,'TimerService'可以在不提供实现的情况下引用这些函数,并且在运行时对象实例将提供正确的功能 - 如展示的那样。请参阅'handleTimerEvent'。 – kfsone

+0

这并不完全清楚你为什么要将'TimerService'从'A'中分离出来。你的另一种选择是只做所有这一节课。 'boost :: asio'和线程系统不关心你叫*你的班级。 – kfsone