0

I have the below five files.

I am trying to call a function in two_b.cpp from one_a.cpp using a std::function callback, but I get the following error:

terminate called after throwing an instance of 'std::bad_function_call'
  what():  bad_function_call
Aborted (core dumped)

one_a.h

#include <functional>

using CallbackType = std::function<void()>;

class Car {
  public:
    void car_run(void);
    void car_stop(void);

    CallbackType f1;

private:
  CallbackType callbackHandler;
};

one_a.cpp

#include "one_a.h"
#include <iostream>

void Car::car_run(void)
{
    std::cout<<"Car running"<<std::endl;
}

void Car::car_stop(void)
{
    std::cout<<"Car stopping"<<std::endl;
}

two_b.h

#include "one_a.h"

class Boat {
  public:
    Boat(Car& car_itf);
    static void boat_run(void);
    static void boat_stop(void);
 private:
    Car& car_itf_;
};

two_b.cpp

#include "two_b.h"
#include <iostream>

Boat::Boat(Car& car_itf):car_itf_{car_itf}{
    car_itf_.f1 = std::bind(&Boat::boat_run);
}

void Boat::boat_run(void)
{
    std::cout<<"Boat running"<<std::endl;
}

void Boat::boat_stop(void)
{
    std::cout<<"Boat running"<<std::endl;
}

main.cpp

#include "two_b.h"

int main()
{
    Car bmw;
    bmw.car_run();
    bmw.f1();

    return 0;
}

A running example can be found here:

https://www.onlinegdb.com/_uYHXfZsN

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
ganeshredcobra
  • 1,881
  • 3
  • 28
  • 44
  • 3
    You never set `f1` to any valid funtion. – Yksisarvinen Apr 12 '22 at 14:15
  • This doesn't address the question, but this code introduces a great deal of overhead with no apparent purpose. `using CallBackType = void (*)();` and `car_itf_.f1 = &Boat::boat_run;` would both do the same thing as those uses of `std::function` and `std::bind` without the indirection that each of those things introduces. Of course, in a more complex program than this example, either or both of those might be needed. – Pete Becker Apr 12 '22 at 14:22
  • @PeteBecker Nevermind, I don't know why I couldn't see the `static` before. Maybe I was looking at `Car` and thinking `Boat` was setup the same way. Oh well... – Remy Lebeau Apr 12 '22 at 19:17

1 Answers1

1

std::function throws a std::bad_function_call exception if you try to invoke it without having a callable target assigned to it.

So, you need to actually assign a target to f1 before you try to invoke f1 as a function. You are doing that assignment in Boat's constructor, so you need to create a Boat object first, eg:

int main()
{
    Car bmw;
    Boat ferry(bmw); // <--
    bmw.car_run();
    bmw.f1();

    return 0;
}

Online Demo

Also, make sure to clear f1 in Boat's destructor, so you don't leave the f1 dangling, eg:

Boat::~Boat(){
    car_itf_.f1 = nullptr;
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770