2015-06-21 27 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