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.
Related
When publicly inheriting a class, why can't I define a function of the base class using name of derived class if the public members of base class are inherited by that derived class?
Example:
#include <iostream>
using namespace std;
class one{
int a;
public:
void get(int);
void show();
};
class two:public one
{
int b;
public:
void getb(int);
void dis();
};
void one::get(int x) //if i write void two::get(int x) here it gives error
{
a = x;
}
void one::show() //same goes for this function why can't i define it as `void two::show()`?
{
cout << a << endl;
}
int main()
{
two ob;
int x;
cin >> x;
ob.get( x );
ob.show();
}
So if if all public member functions of class one are inherited by class two, why can't I define functions of class one using name of class two ?
Why ?
In the class definition, you say that two inherits from one. So it will have the following public members:
void get(int); publicly inherited from one
void show(); publicly inherited from one
void getb(int); own member
void dis(); own member
You can define only the own member functions of two, here two::getb(int) and two::dis(). But you can't define two::show() because it was defined in one and you did not tell the compiler that you wanted it.
Is there a way to do have a different version of the inherited functions ?
If you'd define the class as follows:
class two:public one
{
int b;
public:
void getb(int);
void dis();
void show(); //yes you can, but you'll have to define it
};
then you would have the following public members:
void get(int); publicly inherited from one
void one::show(); publicly inherited from one but hidden
void show(); own member
void getb(int); own member
void dis(); own member
you could define the following:
void two::show() //no problem !!
{
cout << "two's version" << endl;
}
You could even choose in main() which one you want to call:
ob.get( x ); // one::get(), because there's no two::get()
ob.show(); // by default two::show(), because ob is a two
ob.one::show(); // yes you can !!
Here an online demo
Want polymorphism ?
In all the code above, the function invoked depend on the type used to access the object:
one *pob = &ob; // a one pointer can point to a two object
pob->show(); // but this will invoke one::show()
If you'd prefer the right function be called depending on the real type of the object, and not the type assumed from the type declaration, you'd need to use virtual functions and override them:
class one{
... (the rest as before) ...
virtual void show();
};
class two:public one
{
... (the rest as before) ...
void show() override;
};
Then, whenever you invoke show(), the correct function will be called (online example), unless you specifically inkove a precisely specified version by using a fully qualified identifier.
In this code I am storing the address of object B in pointer type object of A.
If I call the function then the program must run the function of second class but it doesn't work and run function of 1st class.
If I put virtual before the parental class function then it moves towards other class function.
When I stored 2nd class address in pointer type object, program have to show 2nd class function. But it couldn't do this.
Why this is so?
#include<iostream>
using namespace std;
#include<conio.h>
class a
{
public:
void fun()
{
cout << "1st";
}
};
class b:public a
{
public:
void fun()
{
cout << "2nd";
}
};
class c :public a
{
public:
void fun()
{
cout << "3rd";
}
};
void main()
{
a *A;
b B;
c C;
A = &B;
A->fun();
_getch();
}
When i stored 2nd class address in pointer type object, program have to show 2nd class function...
Not, it does not. In C++ functions are associated with classes (types), not objects. So compiler looks at the type of the pointer your functions is called through. Then, it tries to find such function in the corresponding class definition.
In your case compiler sees "call to the function fun() through the pointer of type A" and it simply translates it to the address of fun() from class A.
*The callable function is stored elsewhere, but not inside the object.
Indeed, this is the point of "statically typed" languages: compiler looks at your object through the prism of the object`s type.
However, as was mentioned, if you want to make association of a function with particular object, you need to use the keyword virtual. This will create a virtual table for each object of class A (and all inherited from A). Then addresses of all functions marked is virtual will be stored inside this virtual table. Consequently, when inheriting class has its own implementation of a virtual function, the address of the new implementation will override the previous address inside the object`s virtual table.
Now, when you call fun() through the pointer of class A the control flow (now during the runtime) will make a lookup to the objects virtual table and will find an address to the function you expect.
class A
{
public:
virtual void fun()
{
cout << "1st";
}
};
class B
{
public:
void func() override
{
cout << "2nd";
}
}
void main()
{
a *A;
b B;
A = &B;
A->fun(); // -> "2nd"
// function address deduced at runtime
}
You need to use virtual keyword, otherwise inheritance might not work as you expected.
So change your class a as follows:
class a
{
public:
virtual void fun()
{
In c++, pointers are static. This means that they are always looking for the parent's functions, even if they are pointing to a child class. You can avoid this by declaring a:fun as virtual. Take a look at this:
http://www.cplusplus.com/doc/tutorial/polymorphism/
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).
I have a somewhat basic question on inheritance that i can seem to figure out, I've done a search and not found what I was looking for so I thought I'd ask here (not sure if title of what I'm looking for is correct).
To keep things simple I've made a bit of example code to illustrate what I'm not getting.
Basically if I have a parent class A and two child classes B & C,
where A contains common stuff (say an id with get/set),
while B & C have functions that are class specific.
If you declare a class B like: A *bObject = new B();
how do you then access the class specific functionbObj->specific()`?
I've tried virtual but that requires both B & C to have the same function name / prototype declared.
I've also tried declaring the abstract in A, but that requires it to be prototype to be in A.
Where am i going wrong here? any help on this, probably basic issue would be helpful.
#include <iostream>
using namespace std;
// A class dec
class A
{
public:
A(void);
~A(void);
char id;
void setId(char id);
char getId();
};
// B class dec - child of A
class B :
public A
{
public:
B(void);
~B(void);
void sayHello();
};
//C class dec - child of A
class C :
public A
{
public:
C(void);
~C(void);
void sayGoodby();
};
//a stuff
A::A(void)
{
}
A::~A(void)
{
}
void A::setId(char id)
{
this->id = id;
}
char A::getId()
{
return this->id;
}
//b stuff
B::B(void)
{
this->setId('b');
}
B::~B(void)
{
}
// c stuff
C::C(void)
{
this->setId('c');
}
C::~C(void)
{
}
void C::sayGoodby()
{
std::cout << "Im Only In C" << std::endl;
}
// main
void main ()
{
A *bobj = new B();
A* cobj = new C();
std::cout << "im class: " << bobj->getId() << endl;
bobj->sayHello(); // A has no member sayHello
std::cout << "im class: " << cobj->getId() << endl;
cobj->sayGoodby(); // A has no member sayGoodby
system("PAUSE");
}
Thank you for your time!
To access methods unique to a derived class, you need to cast the base class pointer to the correct derived class type first (a downcast):
A *bobj = new B();
bobj->sayHello(); // compile error
dynamic_cast<B*>(bobj)->sayHello(); // works
dynamic_cast<C*>(bobj)->sayGoodbye(); // run-time error - probably crashes with a segfault/access violation.
dynamic_cast ensures run-time type safety but adds a small overhead to the cast; for pointer casts, it returns a null pointer if the pointed-to object is not actually a B, and you should check the return value before using it. Alternatively, if you are really sure that the pointer you are casting is pointing to the correct object, you can use static_cast which saves you the cost of the run-time checking, but if the pointer is not pointing to the right object, you get undefined behavior.
A *bobj = new B();
A* cobj = new C();
Here instance of B and C is pointed by pointer of A. Since A have no virtual function for B and C's member function sayHello() and sayGoodbye(), they could not called by bobj->sayHello() and cobj->sayGoodbye(). It is not what polymorphism should be do.
Class A should be:
class A
{
public:
A(void);
~A(void);
char id;
void setId(char id);
char getId();
virtual void sayHello(){/* to do */ };
virtual void sayGoodbye(){ /* to do */ };
};
Then the bobj->sayHello(); and cobj->sayGoodbye(); could be called without complaning.
A *bobj = new B();
The static type of bobj is A *. So, at compile time, the compiler looks for the member functions in the class A definition, what ever you tried to access through bobj. Now,
bobj->sayHello();
the compiler will look for the sayHello in class A since the type of bobj is A *. Compiler doesn't care to look into the class B definition to resolve the call. Since the compiler didn't find it sayHello member in A, it is complaining.
However, the dynamic type of bobj is B * and that is a where call is dispatched depending on the dynamic type.
To resolve the issue, you need to virtual functions of the same in class A.
if you really want to call a function like this, you can do like this:
A* bobj = new B();
((B*)bobj)->sayHello();//this can be dangerous if bobj is not an instance of class B
however, the problem here is you do the design wrongly.
basically, if you create an class A, and subclass it to B and C.
And then assign A* bobj = new B(); you are splitting the interfaces and implementations. That means you will use bobj as if it is an instance of class A. and you will not call the functions in B or C. B & C are implementations of interface class A.
it's just like you hire someone to build your house. You give them your blueprint(interfaces) and hire them to build. you can alter the blueprint as you like, they will do whatever in blueprint. but you can't order them directly(just like you can't call the sayHello() directly from bobj).
You can use a down cast via dynamic_cast<>. You can implement a template method in your base class A to facilitate the down cast:
class A
{
public:
A(void);
virtual ~A(void);
char id;
void setId(char id);
char getId();
template <typename CHILD, typename R, typename... ARGS>
R invoke (R (CHILD::*m)(ARGS...), ARGS... args) {
CHILD *child = dynamic_cast<CHILD *>(this);
if (child) return (child->*m)(args...);
std::cout << "down cast error: " << typeid(CHILD).name() << std::endl;
}
};
If that particular instance of A was not the base of CHILD, then dynamic_cast<CHILD *>(this) result in NULL. Note that the virtual destructor in A is required for the dynamic_cast<> to work.
So, you can use it like this:
std::unique_ptr<A> bobj(new B());
std::unique_ptr<A> cobj(new C());
bobj->invoke(&B::sayHello);
bobj->invoke(&C::sayGoodbye);
cobj->invoke(&B::sayHello);
cobj->invoke(&C::sayGoodbye);
Only the first and last invocations are valid. The middle two will cause the "down cast error" message to be printed.
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.