类通过回调提供数据

时间:2019-05-17 09:32:37

标签: c++ visual-c++

最近在C语言中进行了一段时间的编程后,我又回到了Visual C ++,其中回调更加容易。

我有一个单例类,该类控制0 .. *连接的设备。 我的想法是在此类中创建一个函数,该函数将遍历一组 连接的设备,并通过回调将其发布到可能需要的任何地方。

例如

SELECT 
    EmailHash,
    DATE(MAX(OrderDate)) AS max_ord_date
    FROM `project.dataset.Header`
    WHERE Date(OrderDate) = '2019-05-15'
    # AND mb_company = 'CORE'
    AND CancelledFlag IS NOT True
    AND AmountPaid > 0
    # Exclude these order numbers
    AND ordernumber NOT IN (
        SELECT ordernumber FROM(
            SELECT 
            ordernumber,
            SUM(SAFE_CAST(StockOutQuantity AS INT64)) AS so,
            SUM(QuantityCancelled) AS cx,
            SUM(Quantity) AS ord
            FROM `project.dataset.Detail`
            WHERE Date(OrderDate) = '2019-05-15'
            GROUP BY ordernumber
            HAVING so = ord)
        UNION 
        SELECT ordernumber FROM(
            SELECT 
            ordernumber,
            SUM(AmountPaid) ap,
            ROUND(SUM(AmountPaid) - (SUM(PnPOrder) + SUM(PnPOrderTax)),2) ap_ntx,
            SUM(RefundedValue) rv,
            SUM(GoodsNet) gn
            FROM `project.dataset.Header`
            WHERE Date(OrderDate) = '2019-05-15'
            GROUP BY ordernumber
            HAVING (ap = rv) OR (ap_ntx = rv) OR (gn = rv)
            )
    )
    GROUP BY EmailHash

在第一个实例中,使用者是MFC对话框类,如果其回调是静态的,则它可以正常工作。但是,为了访问对话框类的成员数据/函数,我需要将'this'传递给singleton类并将其反映回来。

例如

Singleton class

typedef void (CALLBACK * PortListCallback_t)(ptrConstCComPortInfo_t);
.
.
.

void CCommsMgr::listPorts(PortListCallback_t cb)
{
    PortInfoSetConstIter_t i;
    for (i = m_setPorts.begin(); i != m_setPorts.end(); i++)
    {
        cb(*i);
    }
}

我的问题-有更好的方法吗?静态函数感觉就像是一团糟,我不希望Singleton类受到使用方式的限制。 如果我删除了getPorts上的静态内容,它将无法编译。再说一遍,Singleton类应该不了解它的使用者。

1 个答案:

答案 0 :(得分:0)

在WhozCraig的出色提示的帮助下,这就是我想到的:

#include <functional> // std::function, std::bind, std::placeholders
#include <iostream>
#include <vector>

class ConstCComPortInfo {};

using ptrConstCComPortInfo_t = ConstCComPortInfo*;
using callback_t = void(void*, ptrConstCComPortInfo_t);
using function_t = std::function<callback_t>;

// an example class with a member function to call
class foo {
public:
    foo(const std::string& name) : instance_name(name) {}

    void bar(void* something, ptrConstCComPortInfo_t c) {
        std::cout << "foo::bar(" << instance_name << ") called\n"
                     "void* = " << something << "\n"
                     "ptrConstCComPortInfo_t = " << c << "\n";
    }

private:
    std::string instance_name;
};

// and a free function to call
void free_func(void* something, ptrConstCComPortInfo_t c) {
    std::cout << "free_func_called\n"
                 "void* = " << something << "\n"
                 "ptrConstCComPortInfo_t = " << c << "\n";
}

int main() {
    // some instances of the class
    foo via_bind("called_via_bind");
    foo via_lambda("called_via_lambda");

    ptrConstCComPortInfo_t bork = nullptr; // dummy value

    // a vector of callback subscribers
    std::vector<function_t> subscribers{
        &free_func,
        std::bind(&foo::bar, &via_bind, std::placeholders::_1, std::placeholders::_2),
        [&via_lambda](void* p, ptrConstCComPortInfo_t c) { via_lambda.bar(p, c); }
    };

    // perform callbacks
    for(auto& cb : subscribers) {
        cb(nullptr, bork);
    }
}

输出:

free_func_called
void* = 0
ptrConstCComPortInfo_t = 0
foo::bar(called_via_bind) called
void* = 0
ptrConstCComPortInfo_t = 0
foo::bar(called_via_lambda) called
void* = 0
ptrConstCComPortInfo_t = 0