I have a class, A, which requires static event handlers. I needed the static event handlers because an interrupt is calling the event handler.
class A {
private:
static void (*fn1)();
public:
A();
static void setFn1(void (*function)(void));
static void onEvent();
};
A::A() { }
void A::setFn1(void (*function)(void)) {
fn1 = function;
}
void A::onEvent() {
A::fn1();
}
I want to inherit A based upon the application and create the event
handler logic in the child, using fn2 here.
class B : public A{
public:
B();
void fn2();
};
B::B() {
A::setFn1(&fn2);
}
void B::fn2() {...}
When I call: A::setFn1(&fn2) I get the following compiler error.
#169 argument of type "void (B::)()" is incompatible with parameter of type "void ()()
My mind is all loopy with these void-pointers and I do not know if I am even using the proper design anymore. The A class contains all my utility methods. The B class contains my application specific functionality.
A non-static member function is not a free function, the types differ. You cannot use a non-static member function as if it was a pointer to a function:
struct test {
void foo();
static void bar();
};
&test::foo --> void (test::*)()
&test::bar --> void (*)()
I won't go in as much as recommending changing the function to be static as I don't find the current design particularly useful. But you can take this and try to rethink a design that will make more sense. (A single callback function for all the process? Why inheritance at all? A user-defined constructor that does the same as the compiler generated? In a class that should not be instantiated?...)
When I call: A::setFn1(&fn2) I get the following compiler error.
fn2 is a member function of a B, so you have to qualify its name:
A::setFn1(&B::fn2)
// ^^^
Moreover, fn2 should be static, because non-static member functions actually work on an implicit this pointer, so they are accepting an argument:
class B : public A{
public:
B();
static void fn2();
// ^^^^^^
};
With these two changes, your program should compile.
Related
It is very easy that we can make sure derived class must implement interface defined in base class.
That is pure virtual function.
For example:
class BaseClass
{
...
virtual void print()=0;
...
}
class DerivedClass :public BaseClass
{
// function must be implement, otherwise compiler will complain ...
void print()
{
}
};
Can we defined a static interface in base class and make sure the interface must be implement in derivate class?
I want something like this
class BaseClass
{
...
static void print(); // base class only define static interface
...
}
class DerivedClass :public BaseClass
{
// derived class must implement interface, otherwise compiler will complain ...
static void print()
{
}
};
I have no idea about this.
Thanks for your time.
It is not possible to make a virtual static function. For the simple reason that when calling a static function, you always know the class that defines that function in compile time. Unlike virtual functions, where you don't know the type of the object whose method you're calling.
For example:
class A
{
public:
virtual void f() {printf("A");}
};
class B : public A
{
virtual void f() override {printf("B");}
};
void g(A& a)
{
a.f();
}
int main()
{
B b;
g(b);
return 0;
}
In the above example, inside the function g, the correct function is invoked (B::f). Even though while compiling the function it is not known what the type of its argument is (it could be A or any class derived from A).
Without making f() virtual, you would have overloaded the method f, rather than overridden it. Which means that in the following example, the output would be "A", even though you might expect it to be "B":
class A
{
public:
void f() {printf("A");}
};
class B : public A
{
void f() {printf("B");}
};
void g(A& a)
{
a.f();
}
int main()
{
B b;
g(b);
return 0;
}
This may cause serious bugs, and it is suggested to never overload base class methods, and to always use the override keyword when overriding a virtual method to escape those bugs.
When making a static function, you can simply overload it, it would not create a compilation error. However, you probably never should overload it, because it may hide a bug that is very difficult to track (you are certain that B::f() is being called while actually A::f() is being called).
Furthermore, it is not possible to 'force' the derived class to implement a static interface, because there is no such thing as a static interface. Because you have no virtual static functions, you may not pass a reference or pointer to the interface that would implement this function.
I'm thinking of the way how to call most base virtual function given a pointer to a base class and pointer to most base virtual function of that class. This call should happen in outher module, e.g. Invoker, this module shouldn't know anything about class and function it's calling.
Need to build event-emitting system that will not respect virtuality of the callbacks and call exactly that target's function which address was passed to Invoker.
I want to make mandatory for derived classes to use their own callbacks and subscriptions and in general don't do virtual callback in the hierachy. If client still needs something alike, he can try to use virtual handlers in non-virtual callback of the base class.
I tried all kind of casts. Doesn't help, maybe I use them wrong...
#include <iostream>
class A
{
public:
virtual void Foobar() { std::cout << "A" << std::endl; }
};
class B : public A
{
public:
virtual void Foobar() { std::cout << "B" << std::endl; }
};
using CallbackType = void(A::*)();
void Invoker(A* target, CallbackType function)
{
(target->*function)();
}
int main()
{
A a;
B b;
Invoker(&a, &A::Foobar);
Invoker(&b, &A::Foobar);
b.A::Foobar(); // how to make similar call inside Invoker(&b, &A::Foobar) ?
return 0;
}
The output will be:
A
B
A
I want Invoker somehow to call the most base function, so expected output is:
A
A
A
It's not possible to do this with a pointer to member function. Instead, a lambda would be more appropriate:
Invoker(&b, [](A& a) { a.A::Foobar(); });
You need to rewrite Invoker as a template so that it can accept both lambdas and pointers to members:
template <class F>
void Invoker(A* target, F&& function) {
std::invoke(std::forward<F>(function), *target);
}
From what I know, it's impossible.
You can't call a virtual function in a non-virtual manner through a member function pointer.
Well, the lambda solution presented in the other answer is indeed the way to go.
However, I found a way to do what you want ... sort of. The downside is that it involves a slicing copy of the object:
void Invoker(A* target, CallbackType function)
{
(static_cast<A>(*target).*function)();
}
or
void Invoker(A target, CallbackType function)
{
(target.*function)();
}
In class A I have a member function that should receive a pointer to functions from other classes. All those functions have the same signature (receive type and return type).
Something like this:
class A{
private:
void (*onConfirmCallback) (); //pointer to function
public:
void setOnConfirmListener(void (*callback) ()); //member function that receives another member function from another class, and uses the pointer above to point to it
}
definitions:
void A::setOnConfirmListener(void (*callback)())
{
onConfirmCallback = callback;
}
and at some point in class A I call the callback:
onConfirmCallback();
In class B I set the callback:
class B{
private:
A a;
public:
B();
foo();
}
and definitions:
B::B(){
a.setOnConfirmListener(foo);
}
B::foo(){
cout << "foo called" << endl;
}
I also have another class C which also has an instance of A, and also sets a callback:
class C{
private:
A a;
public:
C();
foo2();
}
and definitions:
C::C(){
a.setOnConfirmListener(foo2);
}
C::foo2(){
cout << "foo2 called" << endl;
}
I tried different declaration variations, and the above code generates this error:
no matching function for call to 'A::setOnConfirmListener()'
I understand that "pointers to functions" differ from "pointers to member functions". So I also tried changing void (*onConfirmCallback) () to void (B::*onConfirmCallback) () , but I don't think that's good because this pointer should hold callbacks to different classes (that don't derive from the same base class) and not only B.
Is there a way to implement this?
Basically I'm trying to do something like Java's interface...
Use std::function rather than function pointers.
class A {
private:
std::function <void()> onConfirmCallback; //pointer to function
public:
void setOnConfirmListener(std::function <void()>);
};
You can pass non-member functions directly to setOnConfirmListener. When it comes to member functions, you need an object in order to call them:
class B {
private:
A a;
public:
B();
void foo();
};
B::foo(); // invalid and makes no sense
B* b = new B; b->foo(); // OK
so the line below won't work either:
a.setOnConfirmListener(&B::foo); // invalid and makes no sense
You can pass an object together with its member function using std::bind:
a.setOnConfirmListener(std::bind(&B::foo, b)); // OK
b can be either B&, B* or std::shared_ptr<B>.
It could be a bit dangerous to use this (or *this) as the second argument for bind because you are now responsible to monitor when your object ceases to exist and unregister all its associated listeners. One way round this is to derive your objects from enable_shared_from_this and use std::shared_ptr instead of the raw this pointer. This means your object is not destroyed until it is registered as a listener in at least one callback.
An alternative is to derive all of your listeners from the same abstract base class, say Listener, and use pointers to Listener instead of function pointers.
class Listener
{
public:
virtual void callback() = 0;
};
class A {
private:
std::shared_ptr<Listener> listener; // or another smart pointer
public:
void setOnConfirmListener(std::shared_ptr<Listener> listener);
};
class B : public Listener {
private:
A a;
public:
B();
void foo();
void callback() { foo(); }
};
The downside is the necessity to derive all of your listeners from the same base class. Also, if the same class needs to have more than one listener callback, you have to jump through some hoops.
I have a class that contains some functions (none are virtual) and 2 more classes publicly inherit that class. In both the sub classes I override the same function of the base class.
After creating objects of all three classes in main (located at the same file), I call the original function with the baseclass object and the overridden functions with the derivedclass objects.
I was expecting all 3 function calls to run the original function from the base class (since I didn't use 'virtual' anywhere in the code), but I actually get each version of that function working according to the class in which it was defined (3 different versions).
I have the classes Base & Derived as follows:
struct Base
{
void foo();
};
struct Derived : Base
{
void foo();
};
in main:
int main()
{
Derived d;
d.foo();
}
I thought d.foo() should run Base::foo() if not using 'virtual'.
This is not "overriding"... and it doesn't need to be.
struct Base
{
void foo();
};
struct Derived : Base
{
void foo();
};
int main()
{
Derived d;
d.foo();
}
If I understand you correctly, then you were expecting this to execute Base::foo(), because the functions are not virtual and therefore one does not override the other.
But, here, you do not need virtual dispatch: the rules of inheritance simply state that you'll get the right function for the type of the object you run it on.
When you need virtual dispatch/overriding is a slightly different case: it's when you use indirection:
int main()
{
Base* ptr = new Derived();
ptr->foo();
delete ptr;
}
In the above snippet, the result will be that Base::foo() is called, because the expression ptr->foo() doesn't know that *ptr is really a Derived. All it knows is that ptr is a Base*.
This is where adding virtual (and, in doing so, making the one function override the other) makes magic happen.
You cannot override something that isn't virtual. Non-virtual member functions are dispatched statically based on the type of the instance object.
You could cheat by "overriding" a function by making it an inline function calling something indirectly. Something like (in C++03)
class Foo;
typedef int foo_sig_t (Foo&, std::string&);
class Foo {
foo_sig_t *funptr;
public:
int do_fun(std::string&s) { return funptr(*this,s); }
Foo (foo_sig_t* fun): funptr(fun) {};
~Foo () { funptr= NULL; };
// etc
};
class Bar : public Foo {
static int barfun(Bar&, std::string& s) {
std::cout << s << std::endl;
return (int) s.size();
};
public:
Bar () : Foo(reinterpret_cast<foo_sig_t*>)(&barfun)) {};
// etc...
};
and later:
Bar b;
int x=b.do_fun("hello");
Officially this is not overloading a virtual function, but it looks very close to one. However, in my above Foo example each Foo instance has its own funptr, which is not necessarily shared by a class. But all Bar instances share the same funptr pointing to the same barfun.
BTW, using C++11 lambda anonymous functions (internally implemented as closures), that would be simpler and shorter.
Of course, virtual functions are in generally in fact implemented by a similar mechanism: objects (with some virtual stuff) implicitly start with a hidden field (perhaps "named" _vptr) giving the vtable (or virtual method table).
If I have a code like this:
struct A {
virtual void f(int) {}
virtual void f(void*) {}
};
struct B : public A {
void f(int) {}
};
struct C : public B {
void f(void*) {}
};
int main() {
C c;
c.f(1);
return 0;
}
I get an error that says that I am trying to do an invalid conversion from int to void*. Why can't compiler figure out that he has to call B::f, since both functions are declared as virtual?
After reading jalf's answer I went and reduced it even further. This one does not work as well. Not very intuitive.
struct A {
virtual void f(int) {}
};
struct B : public A {
void f(void*) {}
};
int main() {
B b;
b.f(1);
return 0;
}
The short answer is "because that's how overload resolution works in C++".
The compiler searches for functions F inside the C class, and if it finds any, it stops the search, and tries to pick a candidate among those. It only looks inside base classes if no matching functions were found in the derived class.
However, you can explicitly introduce the base class functions into the derived class' namespace:
struct C : public B {
void f(void*) {}
using B::f; // Add B's f function to C's namespace, allowing it to participate in overload resolution
};
Or you could do this:
void main()
{
A *a = new C();
a->f(1); //This will call f(int) from B(Polymorphism)
}
Well I think first of all you did not understand what virtual mechanism or polymorhism. When the polymorphism is achieved only by using object pointers. I think you are new to c++. Without using object pointers then there is no meaning of polymorphism or virtual keyword use base class pointer and assign the desired derived class objects to it. Then call and try it.