Java-like listeners in C++ I'm coming from languages like Java and Python and I'm completely new to C++. Therefore, my knowledge is somewhat limited.
My goal is to implement a listener in C++ myself and I came up with a solution using function pointers and lambdas.
The design is different from other questions that I have seen on this site so I hope it's not a duplicate.
My question: Is my implementation optimal or is it good from a C++ point of view? If there are any optimizations or any better ways please let me know. (Below code is just an example of my design)
class IntegerListener {
public :

    void (*number_changed)(int old_number, int new_number);

    void (*number_increased)(int increased_value);

    //deleting default constructor to make users to define number_changed and number_increased
    IntegerListener() = delete;

    IntegerListener(void (*&amp;&amp;number_changed)(int, int), void (*&amp;&amp;number_increased)(int)) {
        this-&gt;number_changed = number_changed;
        this-&gt;number_increased = number_increased;
    }

};

class Integer {

private:
    int number;
    std::vector&lt;IntegerListener *&gt; integer_listeners;
public:

    explicit Integer(int num) : number(num) {}

    void set_number(int new_number) {
        for (IntegerListener *&amp;integer_listener:integer_listeners) {
            (*integer_listener).number_changed(number, new_number);
        }
        if (new_number &gt; number) {
            for (IntegerListener *&amp;integer_listener:integer_listeners) {
                (*integer_listener).number_increased(new_number - number);
            }
        }
        number = new_number;
    }

    void add_number_changed_listener(IntegerListener &amp;&amp;integer_listener) {
        integer_listeners.push_back(&amp;integer_listener);
    }
};

and in order to add some listener my idea is something like below:
void test() {
    Integer integer(1);

    // from a java background it represents the java way the best, in my opinion.
    integer.add_number_changed_listener(IntegerListener(
            [](int oldNum, int newNum) {
                std::cout &lt;&lt; &quot;changed(from 1listener): (&quot; &lt;&lt; oldNum &lt;&lt; &quot;) -&gt; (&quot; &lt;&lt; newNum &lt;&lt; &quot;)&quot; &lt;&lt; std::endl;
            },
            [](int increasedValue) {
                std::cout &lt;&lt; &quot;increased by(from 1listener): (&quot; &lt;&lt; increasedValue &lt;&lt; &quot;)&quot; &lt;&lt; std::endl;
            }));

    integer.add_number_changed_listener(IntegerListener(
            [](int oldNum, int newNum) {
                std::cout &lt;&lt; &quot;changed(from 2listener): (&quot; &lt;&lt; oldNum &lt;&lt; &quot;) -&gt; (&quot; &lt;&lt; newNum &lt;&lt; &quot;)&quot; &lt;&lt; std::endl;
            },
            [](int increasedValue) {
                std::cout &lt;&lt; &quot;increased by(from 2listener): (&quot; &lt;&lt; increasedValue &lt;&lt; &quot;)&quot; &lt;&lt; std::endl;
            }));
    std::cout &lt;&lt; &quot;first call: \n&quot;;
    integer.set_number(2);
    std::cout &lt;&lt; &quot;second call: \n&quot;;
    integer.set_number(1);
}
There’s actually quite a bit you can do to simplify the listener class, while at the same time making it easier and more flexible to use!
Let’s start with deleting the default constructor: you actually don’t need to do this. Classes get an automatically-generated default constructor only if there are no other constructors defined. But in your class, there is another constructor defined! So the default constructor is already deleted.
See for yourself! Try this:
// No constructors are defined, so the class gets a default constructor.
class foo {};

// A constructor is defined, so the default constructor is suppressed.
class bar
{
public:
    explicit bar(int) {}
};

// This will compile:
auto f = foo{};

// This will not:
//auto b1 = bar{};

// But of course, this will compile:
auto b2 = bar{42};

So right away, you can drop the line deleting the default constructor.
Now, this is not wrong:
void (*number_changed)(int old_number, int new_number);

void (*number_increased)(int increased_value);

That is indeed the correct way to have two data members that are function pointers.
However…
There is actually a better way:
std::function&lt;void (int, int)&gt; number_changed;
std::function&lt;void (int)&gt; number_increased;

The reason this is better is because std::function is a LOT more powerful than a function pointer. A function pointer only works for regular, free functions, class static functions, and lambdas with no captures.
But std::function works with literally anything that even remotely looks like a function. It works for all the same things a function pointer works for. But it also works for member functions, lambdas with captures (closures), general function objects, bound-argument functions, … and so on and so forth. Like, literally everything works.
For example:
class my_int_listener
{
public:
    void number_changed(int, int) { /* whatever you want */ }
    void number_increased(int) { /* whatever you want */ }

    // This class could have data members, a constructor... whatever
    // you want, and you can use all that stuff in your callbacks.
};

// Constructed however you want, wherever you want - global var, on the
// heap, whatever - just so long as it outlives integer.
auto mil = my_int_listener{};

auto integer = Integer{1};

using namespace std::placeholders;
integer.add_number_changed_listener(
    {
        std::bind(&amp;my_int_listener::number_changed, &amp;mil, _1),
        std::bind(&amp;my_int_listener::number_increased, &amp;mil, _1)
    }
);

The other benefit of std::function is the syntax is soooo much nicer. Function pointers are ghastly. Even when I’m forced to use them, I always use typedefs to hide the ugliness:
class IntegerListener {
public :
    using number_changed_function = void (*)(int, int);
    using number_increased_function = void (*)(int);

    number_changed_function number_changed = nullptr;
    number_increased_function number_increased = nullptr;

    IntegerListener(number_changed_function&amp;&amp; number_changed, number_increased_function&amp;&amp; number_increased) {
        this-&gt;number_changed = number_changed;
        this-&gt;number_increased = number_increased;
    }
};

That just looks a lot more like natural C++. And of course, with std::function:
class IntegerListener {
public :
    std::function&lt;void (int, int)&gt; number_changed = nullptr;
    std::function&lt;void (int)&gt; number_increased = nullptr;

    IntegerListener(std::function&lt;void (int, int)&gt;&amp;&amp; number_changed, std::function&lt;void (int, int)&gt;&amp;&amp; number_increased) {
        this-&gt;number_changed = number_changed;
        this-&gt;number_increased = number_increased;
    }
};

Although you could use typedefs there too, which is probably a good idea for avoiding needless repetition.
The one downside of using std::function over raw function pointers is that std::function objects are larger—sometimes quite a bit larger, in order to do the type erasure necessary to do all its tricks. But unless you want to accept the rather severe restrictions that raw function pointers come with, there’s no other option. (Well, there are other options, but they would require a redesign: you could, for example, you could use a polymorphic base class for your listeners, and use dynamic dispatch.)
Now let’s focus on that constructor:
IntegerListener(void (*&amp;&amp;number_changed)(int, int), void (*&amp;&amp;number_increased)(int)) {
    this-&gt;number_changed = number_changed;
    this-&gt;number_increased = number_increased;
}

I’m not sure why you’d want to use rvalue-references for your constructor parameters here. Did you try something and it would’t compile without them? I can’t see what purpose rvalue-referenes here serve, even theoretically.
The other thing is: when you’re initializing data members, you almost always want to use data member initializers, rather than initializing them in the constructor’s body.
This is probably more what you want:
IntegerListener(void (*number_changed)(int, int), void (*number_increased)(int)) :
    number_changed{number_changed},
    number_increased{number_increased}
{}

Or even more correctly:
IntegerListener(void (*number_changed)(int, int), void (*number_increased)(int)) :
    number_changed{std::move(number_changed)},
    number_increased{std::move(number_increased)}
{}

The moves are because there’s no need to copy the arguments from the function parameters to the data members (assuming you don’t want to use the function parameters again). Moving is more logically correct, and can be much faster (though it doesn’t matter here).
Finally, I can’t imagine any reason why this constructor couldn’t be noexcept. If all it’s doing is just taking the parameters and moving them into the data members, then so long as the moves are noexcept (which, moves should always be noexcept wherever possible, and they are both for raw function pointers and std::function), there’s no chance of failure.
So putting it altogether, if I were writing your listener class, I might do:
class IntegerListener
{
public:
    using number_changed_type = std::function&lt;void (int, int)&gt;;
    using number_increased_type = std::function&lt;void (int)&gt;;

    number_changed_type number_changed = nullptr;
    number_increased_type number_increased = nullptr;

    IntegerListener(
        number_changed_type number_changed,
        number_increased_type number_increased) noexcept :
            number_changed{std::move(number_changed)},
            number_increased{std::move(number_increased)}
    {}
};

Now on to the dispatcher….
std::vector&lt;IntegerListener *&gt; integer_listeners;

I don’t see any reason why you’d want to store pointers to the listeners, rather than just storing the listeners directly. You’re not doing dynamic dispatch (IntegerListener doesn’t have a virtual destructor), and there is no functional difference between storing the objects directly in the vector or storing them remotely. Using pointers for this just means poor performance due to the extra indirection and cache busting, and the need to manage memory, with no benefits.
In fact, as I pointed out in my other comment, what you’re doing is actually just storing the address of temporary objects, which immediately die, leaving you with dangling pointers. If you actually wanted to store pointers, you would have to either manually allocate those pointers (or use global or static objects, I guess)—which means you also have to manually manage that memory with custom copy constructors and a destructor—or (and, really, this is the only option in modern C++… do NOT try manually allocating and managing memory), use smart pointers.
But, as I said, there’s no benefit to using pointers at all, so there’s nothing to be gained from using smart pointers. Just store the objects in the vector directly. It’ll be faster, easier to code, and you won’t end up with critical bugs involving dangling pointers like the one you have (or leaks or double-frees or any of the other crap that comes with manual memory management… seriously do not do manual memory management in C++).
void set_number(int new_number) {
    for (IntegerListener *&amp;integer_listener:integer_listeners) {
        (*integer_listener).number_changed(number, new_number);
    }
    if (new_number &gt; number) {
        for (IntegerListener *&amp;integer_listener:integer_listeners) {
            (*integer_listener).number_increased(new_number - number);
        }
    }
    number = new_number;
}

If you’re going to store pointers in your vectors, there’s really no reason to iterate through them by reference. In fact, you’re just paying for a double indirection which you don’t even use.
But! If you’re going to store the actual listeners in your vectors, then, yes, you should take them by reference… but you should really take them by const reference, because you’re not going to be modifying them.
I generally recommend to use the universal form of range-for. This:
for (auto&amp;&amp; item : range)

always works, for everything, and never does the wrong thing. It should be the default thing you write whenever you write a range-for.
(And no, it is NOT the same as doing for (IntegerListener&amp;&amp; item : range). That usually won’t work… and it won’t work for your case. It’s auto&amp;&amp; or it’s a craps shoot. Only auto&amp;&amp; always works.)
However… if you want to be more explicit about what your code is actually doing, you could do:
for (auto&amp; item : range) // to signal you will be modifying the items
// or
for (auto const&amp; item : range) // if you'll just be reading them

These don’t always work, but they almost always work, and if you really mean what they say—that you’re either modifying the items or you’re definitely not and you’re just inspecting them—then they pretty much always work.
So I’d probably write:
for (auto const&amp; integer_listener : integer_listeners)
    integer_listener.number_changed(number, new_number);

unless I was feeling lazy, in which case I’d use the auto&amp;&amp; form.
void add_number_changed_listener(IntegerListener &amp;&amp;integer_listener) {
    integer_listeners.push_back(&amp;integer_listener);
}

This is really the only broken function in the code. Everything else is correct, though maybe not the most efficient, and maybe not following C++ best practices or styles.
But this function has two problems. First, it takes the argument by rvalue reference. I can’t imagine why you’d want to do that. It doesn’t really make any sense. What you’re saying with that is that you only want to take temporary-constructed integer listeners. In other words, you’re saying:
// this is fine:
integer.add_number_changed_listener(IntegerListener{f1, f2});

// but this is absolutely wrong, and should not compile:
auto il = IntegerListener{f1, f2};
integer.add_number_changed_listener(il);

But why? What’s wrong with making an integer listener and passing it to two integers? Maybe I have two integers that I want to keep track of changes to. Why am I banned from using the same listener for both?
The second problem with this function is that you only take the address of the listener. Even if you weren’t requiring temporary-constructed listeners, that’s an accident waiting to happen, because even if the listener isn’t temporary—which means it’s very likely to die almost immediately—it still might not live long enough to still be active when the dispatcher wants to signal an event.
You have two options here:

either you mandate that users keep listener objects around for as long as needed, and make it their problem to keep track of that (which would be a terrible, bug-prone design); or
you simply keep the listener object with the dispatcher, so it has to stick around as long as the dispatch object exists.

In other words, don’t muck around with pointers and the address-of operator ('&amp;'). Just do the natural thing:
void add_number_changed_listener(IntegerListener integer_listener) {
    integer_listeners.push_back(integer_listener);
}

And even better, and more technically correct: you don’t really want a copy of the listener stored in the vector… you want the actual listener object. So you want to move what you were given into the array:
void add_number_changed_listener(IntegerListener integer_listener) {
    integer_listeners.push_back(std::move(integer_listener));
}

Now as a user of the class, I have control. I get to decide if I want to give you a temporary-constructed listener, or if I want to copy a listener to multiple integers. And no matter what I choose, everything just works.
That’s it for the line-by-line review! Overall, the only “problem” with it that would make me reject it from a code base I was responsible for is that the vector integer_listeners holds pointers rather than actual objects, and those pointers are almost certainly going to be dangling because add_number_changed_listener() only takes temporaries. If you only made two changes:

change integer_listeners to be a std::vector&lt;IntegerListener&gt; (not std::vector&lt;IntegerListener*&gt;); and
change add_number_changed_listener() to store (by copying or—better—moving) the passed listener, not just its address

then I would consider the code acceptable. (Though, of course, there are a number of other improvements you could make, like using std::function rather than raw function pointers`.)
To answer your concerns:

The design is pretty optimal, yes. There are a few minor touch-ups here and there that make it even more efficient, but the basic design is sound. And, actually, it’s a pretty good design, in my opinion.
Is the design good C++? Yes, I think so. Even without the changes I suggested (other than fixing those critical bugs), I’d say it fits well with good C++ philosophy. There are other ways of doing it, of course, and every design has its pros and cons. But this design is, I think, quite good. I’d use it.