Suppose we have an abstract Base class that is inherited:
class Base
{
protected:
Base() {}
virtual ~Base() {}
virtual void on_event_foo(int) {}
virtual void on_event_bar(int) {}
};
struct Concrete : public Base
{
virtual void on_event_foo(int value) {/*do some stuff with @value*/}
};
Is it a way to know (at compile time would be the best) the virtual
functions from Base
that was overridden (with some code in constructor, or with a special pattern)?
My purpose is to implement a wrapper for a library that use some callbacks ; and if I can do check the overriden functions, I will create only the callbacks the user wants.
I want the user can choose the function he wants to override. Then in my code, I will create callbacks only for the overridden functions. The pure virtual
functions are not a solution, because they cannot permit to create a concrete class without overriding all of them.
In the constructor of Base
, for now, I connect a lot of static callback functions of Base
within a C API. In those functions, I call the corresponding member function. For example, the callback function is static Base::EventFoo(/* ... */)
that calls inside object->on_event_foo(/* .. */)
. This is because I cannot give a member function as a callback to a C library.
But creating too much callbacks make my wrapper slower. So, I want to connect only the callback that the user wants, ie knowing the functions there are overriden by him.
getMethod("myMethod"). getDeclaringClass(); If the class that's returned is your own, then it's not overridden; if it's something else, that subclass has overridden it.
When the base class and derived class have member functions with exactly the same name, same return-type, and same arguments list, then it is said to be function overriding.
In C++, there's no way to forbid it, it's just that by definition of "override", only virtual functions can be "overridden".
Overriding is done so that a child class can give its own implementation to a method which is already provided by the parent class. In this case the method in parent class is called overridden method and the method in child class is called overriding method.
If you are willing to change a few things, you can use the curiously recurring template pattern to determine if the function is overridden
#include <iostream>
template <class Derived>
struct Base
{
virtual void on_event() {}
void raise_event()
{
if (&Derived::on_event == &Base::on_event)
std::cout << "not overridden" << std::endl;
else
std::cout << "overridden" << std::endl;
}
};
struct Concrete1 : Base<Concrete1>
{
virtual void on_event() override {}
};
struct Concrete2 : Base<Concrete2>
{
// no override
};
int main()
{
Concrete1 c1;
Concrete2 c2;
c1.raise_event(); // prints overridden
c2.raise_event(); // prints not overridden
return 0;
}
The statement &Derived::on_event == &Base::on_event
should be resolved at compile-time (if that's what you're worried about) and the if
can be optimized away.
Though I agree with others' opinions that this seems like a poor pattern. It would be much simpler to have the base class have empty event handlers like you already have.
Don't use virtual
methods at all. If all you want is given some concrete type, Concrete
, to hook it up to a bunch of callbacks based on the presence of member functions then we can use templates.
For a given type and function name, we can determine if &T::func
exists at compile time. If it does, we add that callback. So we end up with a whole bunch of things like:
template <class T>
void setup_cbs(T& object) {
T* ptr_to_object = ...; // store somewhere
static_if<has_on_event_foo<T>>(
[](auto ptr){
add_event_foo_callback(ptr, [](void* p, int i) {
using U = decltype(ptr);
static_cast<U>(p)->on_event_foo(i);
})
}),
[](auto ){}
)(ptr_to_object);
I'm assuming the callback adder takes a pointer and a callback. You will separately have to figure out how to store the pointers, but that seems easier.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With