Moaaz Ali
Moaaz Ali

Reputation: 93

Keeping reference to member function from other another class

I have an instance of a class A which should register a member callback in another instance of class B. I'm trying to keep the reference to the function of class A inside class B but I get a Segfault.

classA.h:

std::shared_ptr<classB> mB;
void toBeRegisteredCallback(const uint8_t val);

classA.cpp:


classA::classA(std::shared_ptr<classB> b) : 
mB(std::move(b)) {
  b->registerCallback(std::bind(&classB::toBeRegisteredCallback, this,
                                                      std::placeholders::_1));
}

void classB::toBeRegisteredCallback(const uint8_t val) {
  LOG(INFO) << "Received a value callback!";
}

Here is the code for classB.h:

public:
    void registerCallback(std::function<void(const uint8_t val)> callback);
private:
    std::function<void(const uint8_t)> _callback;

Here is code for classB.cpp:

void classB::registerCallback(std::function<void(const uint8_t val)> callback) {
        _callback = callback;
}

When I try to call the callback directly without assignment, it works fine: callback(8) However, if I try to assign it, I get a segfault at functionswap

Thanks.

Upvotes: 0

Views: 81

Answers (2)

G.M.
G.M.

Reputation: 12879

Consider your classA constructor...

classA::classA(std::shared_ptr<classB> b)
  : mB(std::move(b))
{
  b->registerCallback(std::bind(&classB::toBeRegisteredCallback, this,
                                                      std::placeholders::_1));
}

The initialization of mB will invoke (from here(item 10))...

shared_ptr( shared_ptr&& r ) noexcept;

Move-constructs a shared_ptr from r. After the construction, *this contains a copy of the previous state of r, r is empty and its stored pointer is null.

Hence, in the following statement...

b->registerCallback(std::bind(&classB::toBeRegisteredCallback, this, std::placeholders::_1));

b is effectively a null pointer resulting in undefined behaviour.

Upvotes: 1

kali
kali

Reputation: 1

I am not quite sure what you want to do, but I created a working example below. You may give me feedback if that helps you, or if you need more explanation. (As already mentioned by john you should be careful with the std::move command)

#include <memory>
#include <functional>
#include <iostream>

class classB
{
public:
    classB() {}
    ~classB() {}

public:
    void registerCallback(std::function<void(const uint8_t val)> callback)
    {
        _callback = callback;
    }
    void callCallback()
    {
        if(_callback)
            _callback(8);
    }

private:
    std::function<void(const uint8_t)> _callback;
};

class classA
{
public:
    classA(std::shared_ptr<classB> b)
        : mB(b)
    {
      b->registerCallback(std::bind(&classA::toBeRegisteredCallback, this, std::placeholders::_1));
    }
    ~classA(){}

    void toBeRegisteredCallback(const uint8_t /*val*/)
    {
        std::cout << "Received a value callback!" << std::endl;
    }

private:
    std::shared_ptr<classB> mB;    
};

int main(int, char *[])
{
    std::shared_ptr<classB> b = std::make_shared<classB>();
    classA localClassA = classA(b);
    b->callCallback();
    system("pause");
}

Upvotes: 0

Related Questions