簡體   English   中英

使用`std :: function`從另一個對象的成員調用

[英]Invoking member of an object from another one by using `std::function`

我正在嘗試在對象之間創建一個通信系統,其中一個控制器對象保存其他對象的成員函數的向量,並在需要時調用/調用它們。
我讀了幾篇關於std::function用法的文章,但我找不到涵蓋這個用例的文章。

我的代碼是:

#include <functional>
#include <Windows.h>

class Callable
{

};

class ClassA : public Callable
{
    public:
        double CallThis(double x, int y) const
        {
            MessageBoxW(NULL, L"CallThis() is called.", L"In ClassA", MB_ICONINFORMATION);
            return x + y;
        }
};

class ClassB : public Callable
{
    public:
        double CallMe(double x, int y) const
        {
            MessageBoxW(NULL, L"CallMe() is called.", L"In ClassB", MB_ICONINFORMATION);
            return x + y;
        }
};

class Caller
{
    public:
        void AddSubscriber( const Callable & ObjectToCall,
                            const std::function<double(const Callable &, double, int)> & Subscriber)
        {
            Subscribers.push_back(Subscriber);
            ObjectsToBeCalled.push_back(ObjectToCall);
        }
        void CallSubscribers()
        {
            for (size_t i=0; i<Subscribers.size(); i++)
            {
                Subscribers[i](ObjectsToBeCalled[i], 1.0, 2);
            }
        }
    private:
        std::vector<std::function<double(const Callable &, double, int)>> Subscribers;
        std::vector<const Callable &> ObjectsToBeCalled;
};

int APIENTRY wWinMain(  _In_        HINSTANCE   hInstance,
                        _In_opt_    HINSTANCE   hPrevInstance,
                        _In_        LPTSTR      lpCmdLine,
                        _In_        int         nCmdShow)
{
    // ...

    ClassA ObjectA;
    ClassB ObjectB;
    Caller ObjectCaller;
    ObjectCaller.AddSubscriber(ObjectA, &ClassA::CallThis);
    ObjectCaller.AddSubscriber(ObjectA, &ClassB::CallMe);
    Sleep(5000);
    ObjectCaller.CallSubscribers();

    // ...
}

奇怪的是,當我運行此代碼時,我在自己的代碼中沒有得到任何編譯器錯誤,但是我從STL文件xmemory0vector得到錯誤。 錯誤是:

Error 1  xmemory0  527 error C2528: 'pointer' : pointer to reference is illegal
Error 2  xmemory0  528 error C2528: 'const_pointer' : pointer to reference is illegal
Error 3  xmemory0  561 error C2535: 'const Callable &(*std::allocator<_Ty>::address(const Callable &) throw() const)' : member function already defined or declared
Error 4  xmemory0  599 error C2528: '_Ptr' : pointer to reference is illegal
Error 5  xmemory0  604 error C2528: '_Ptr' : pointer to reference is illegal
Error 6  xmemory0  700 error C2528: 'pointer' : pointer to reference is illegal
Error 7  xmemory0  701 error C2528: 'const_pointer' : pointer to reference is illegal
Error 8  xmemory0  824 error C2535: 'const Callable &(*std::_Wrap_alloc<_Alloc>::address(const Callable &) const)' : member function already defined or declared
Error 9  xmemory0  890 error C2528: '_Ptr' : pointer to reference is illegal
Error 10 xmemory0  105 error C2528: 'abstract declarator' : pointer to reference is illegal
Error 11 xmemory0  107 error C2528: 'abstract declarator' : pointer to reference is illegal
Error 12 xmemory0  122 error C2528: 'pointer' : pointer to reference is illegal
Error 13 xmemory0  123 error C2528: 'const_pointer' : pointer to reference is illegal
Error 14 vector    773 error C2528: '_Pval' : pointer to reference is illegal
Error 15 vector   1184 error C2535: 'void std::vector<_Ty>::push_back(const Callable &)' : member function already defined or declared
Error 16 vector   1245 error C2535: 'std::_Vector_iterator<_Myvec> std::vector<_Ty>::insert(std::_Vector_const_iterator<_Myvec>,_Ty)' : member function already defined or declared
Error 17 vector   1494 error C2528: '_Ptr' : pointer to reference is illegal
Error 18 vector   1658 error C2528: '_Pval' : pointer to reference is illegal

我究竟做錯了什么? 如何運行此代碼?

(我的IDE是Microsoft Visual Studio 2012.)

查看代碼,看起來你最好存儲std::function<double(double, int)> ,然后使用std::bind將對象std::bind到成員函數。

template <typename F>
void AddSubscriber( const Callable & obj,
                    F subscriber)
{
    Subscribers.push_back(std::bind(subscriber, obj, _1, _2));
}

或者直接通過將可轉換為std::function<double(double, int)>直接從Caller Callable

class Caller 
{
public:
  template <typename F>
  void AddSubscriber(F&& subscriber)
  {
     subscribers.emplace_back(std::forward<F>(subscriber));
  }
  void CallSubscribers()
  {
      for (const auto& subscriber : subscribers)
      {
          subscriber(1.0, 2);
      }
  }
 private:
  std::vector<std::function<double(double, int)> subscribers;
};

然后從調用者端進行綁定。

Caller c;
ClassA a;
using namespace std::placeholders;
c.AddSubscriber(std::bind(&ClassA::CallThis, a, _1, _2));

在閱讀了juanchopanza的回答之后,我重寫了我的代碼,如下所示。 現在它按預期工作。

class ClassA
{
    public:
        double CallThis(double x, int y) const
        {
            MessageBoxW(NULL, L"CallThis() is called.", L"In ClassA", MB_ICONINFORMATION);
            return x + y;
        }
};

class ClassB
{
    public:
        double CallMe(double x, int y) const
        {
            MessageBoxW(NULL, L"CallMe() is called.", L"In ClassB", MB_ICONINFORMATION);
            return x + y;
        }
};

class Caller
{
    public:
        void AddSubscriber(std::function<double(double, int)> Subscriber)
        {
            Subscribers.push_back(Subscriber);
        }
        void CallSubscribers()
        {
            for (const auto & Subscriber : Subscribers)
            {
                Subscriber(1.0, 2);
            }
        }
    private:
        std::vector<std::function<double(double, int)>> Subscribers;
};

int APIENTRY wWinMain(  _In_        HINSTANCE   hInstance,
                        _In_opt_    HINSTANCE   hPrevInstance,
                        _In_        LPTSTR      lpCmdLine,
                        _In_        int         nCmdShow)
{
    // ...

    ClassA ObjectA;
    ClassB ObjectB;
    Caller ObjectCaller;
    ObjectCaller.AddSubscriber(std::bind(&ClassA::CallThis, ObjectA, std::placeholders::_1, std::placeholders::_2));
    ObjectCaller.AddSubscriber(std::bind(&ClassB::CallMe,   ObjectB, std::placeholders::_1, std::placeholders::_2));
    Sleep(5000);
    ObjectCaller.CallSubscribers();

    // ...
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM