I have been trying to understand function pointers in C++ so that I can successfully use them in one of my projects. I am running into a logic problem though. Say we have two classes: a parent class and a child class which inherits the parent class.
class Parent{
...other stuff
void (Parent::*ptr2func) ();
...other stuff
};
Then we have a child class:
class Child : public Parent{
...other stuff
void afunc();
...other stuff
};
I wanted to connect the pointer of the parent class to the afunc() function of the child class. In the constructor of the child class is where I tried to do it like so:
Child::Child()
{
ptr2func = &Child::afunc;
}
This returned an expected error:
cannot convert void (Child::*)() to void (Parent::*)() in assignment.
I was afraid that such a thing would happen. But how do I get over this? Can't I link a function pointer to a member function of a parent class to a member function of the child class? As you can understand I am trying to achieve polymorphism through function pointers just for experimenting and without using virtual functions. I was lead to believe that this is possible. What is my mistake? Or is it just not possible?
A void (Parent::*)() takes an object of type Parent. The function Child::afunc requires an object of type Child. Converting the pointer to void (Parent::*)() would therefore allow for an invalid call.
Member function pointers can't really be used to implement polymorphism. The traditional way to implement polymorphism without using virtual is to use regular function pointers:
struct MyBaseClass
{
void (*function)(MyBaseClass* this_pointer);
};
It would be dangerous if that conversion worked as you would be able to call a function in class Child with a pointer or reference to a Parent which might not be of type Child.
If you are passing in a function and a pointer/reference you could use a boost::bind to achieve it.
Related
Okay, I tried to put my problem/question in one sentence in the title. I have the following code example:
class ParentClass
{
};
//#include "ParentClass_Header.h"
class SomeOtherClass
{
ParentClass* parent;
public:
virtual void func(ParentClass* parentclass) {
parent = parentclass;
}
};
class ChildClass : public ParentClass
{
public:
};
void SomeOtherClass::func(ChildClass* childclass)
{
}
Anyway, I have a ParentClass which I inherited to a ChildClass. Another (SomeOtherClass) class has to hold some information about the ChildClass (the pointer is needed in the function SomeOtherClass:func(...)).
The compiler says something like the ChildClass* cannot be converted in ParentClass*. I don't think it is possible to do this the way I am trying to do it. The other way would be to declare a ChildClass* child_ptr and assign it with child_ptr = this in any member function (of class ChildClass). But it would be nice to know if there is another, maybe more professional way.
Your declaration and definition of func are different, in the class declaration you give it an argument of ParentClass * whilst you define it with a ChildClass*. If you only want for it to take a ChildClass* as an argument then declare it as such, or vice-versa if you would like the function to take any derived ParentClass*.
I would say however judging by your naming of "Child" and "Parent" that the code seems confused with its aim. It is not normal that a child would be derived from a parent, instead you would expect the parent class to have some form of container that managed the children. In this case one should pass the parent in the constructor if the child needs to communicate backwards to the parent.
Let's say I have a class Child that inherits from class Parent. Both classes need to be able to be able to send a function pointer of the same method, let's call it foo(), to an API.
I don't think I can make foo() a member function, since the process invoking the callback would need to have an object of either Child or Parent to call it with. I also don't think I can make foo() a static member function since there may be multiple instances of Parent of Child.
What would be the cleanest place to put foo() in this case? Should it go into its own file and have its own namespace, and get #include'd into both Parent and Child? Should foo() be in Parent only meaning Child would need to include Parent.cpp and forward declare foo()?
Appreciate any insight!
If your API need a pointer to a function, you can only give it either a static function or a plain function defined outside of any class. If you later need that this function calls a method on one of your objects, you need that the API allows you to pass something (usualy a void *). If you can pass the API the function pointer and a void * you have won: just pass it a pointer to an object of class Parent or Child along with the pointer to a relay function.
Say the API will call a int (*callback)(void *param /* other params...*/)
You define something like:
int myCallback(void* param /* other params...*/) {
Parent *parent = static_cast<Parent *>(param);
return parent->myMethod(/* other params...*/);
}
That way:
the API only knows a plain pointer to function and an opaque void *
you can declare normal (or even virtual methods) in your classes
the relay function is called by the API and in turns calls the methods on your objects
I can understand why Foo() can't be a static function. It might be that the various Child and Parent objects want to have different Foo() functions.
Consider using an interface. Don't send a pointer to a method, but a reference to the interface which has the Foo() method.
I haven't programmed C++ for a few years now, so my C++ is a bit rusty, forgive me if it is C#. I guess you'll understand the Idea.
public interface IMyInterface
{
void Foo();
}
public class Parent : IMyInterface
{
public virtual void Foo()
{
DoSomething();
}
}
public class Child : Parent, IMyInterface
{
public override void Foo()
{
DoSomethingElse()
// if needed call Base.Foo();
}
}
Usage: Suppose you have an object that needs to call the Foo of an object. Alas it doesn't know whether the object is a Parent or a Child. Luckily it does not have to know what it is, it only has to know it has a function Foo. And that is done by promising that the object will implement IMyInterface
public class FooCaller
{
private void CallFoo(IMyinterFace fooToBeCalled)
{
fooToBeCalled.Foo();
}
}
So FooCaller doesn't know whether fooToBeCalled is a Parent or a Child. It only knows that if has a function Foo().
The nice thing about using an interface is that it can also be used if there is no relation between the objects
class Uncle : IMyInterface
{
public void Foo() {...}
}
The Uncle is neither a Parent nor a Child, yet it can still be used by the FooCaller.
Using interfaces instead of base classes gives you the opportunity to focus on the minimal set of functions needed to perform a task. Thus making reuse of code more likely.
class Parent {
public:
void func1(); // Complete meaningful definition in parent given.
virtual HRESULT func2()=0; // Bcoz of this function Parent class is abstract.
};
class Child: public Parent {
public:
void func1(); // Different definition in child.
};
Is this possible in C++ ? I am overriding func1() which is NOT virtual and it already has a definition in parent abstract class.
[assuming here Child extends Parent, unlike what the code snap shows]
Yes it is possible [it is called hiding] - but you will not get a dynamic dispatch behavior.
The static type will define which method will be invoked, and not the dynamic type.
For example:
Parent* p = new Child;
p->func1();
Will invoke Parent::func1()
while:
Child* c = new Child;
c->func1();
Will invoke Child::func1()
No, it's not possible to actually override the definition in the parent (at least when talking about C++, "override" is normally reserved specifically to referring to virtual functions). Instead, defining a function with the same name in the child class simply hides the function in the parent that has the same name (i.e., in the context of a child object, looking for that name will only find the function in the child, not the one in the parent).
If you want to (and the functions have different signatures) you can also get the functions in both the parent and the child treated as overloaded, so a call will try to call whichever matches better:
struct parent {
void func1(char) {}
};
struct child : public parent {
void func1(long) { }
using parent::func1;
};
Now, you get:
child c;
c.func1('a'); // calls parent::func1
c.func1(123L); // calls child::func1
This is yet a third type of behavior though, different from having a virtual function or having a function in the child that hides the one in the parent.
With a virtual function, the selection of which function is called is based on the dynamic type, so if you have a pointer/reference to the base class, the function called depends on whether that refers to an object of the base or derived class.
When you hide the function, the function that's called is based on the static type, so if you call it via a pointer/reference to the base, it calls the base function, even if that actually refers to an object of the derived class. If, however, you use a pointer or reference to (or directly use an instance of) the derived class, it'll invoke the function in the derived class.
With the using statement, you get function overloading, so when you call the function (in the context of the derived class) the function that's called is based on which function's signature is the best match for the parameter(s) you pass.
You can overload it, if they have distinct argument types.
You can hide it, in the sense shown here, so that Child::func1 will be called instead of Parent::func1 in code that knows it's looking at a child instance. However, as amit points out, you don't get dynamic dispatch.
struct StaticParent {
void foo();
};
struct StaticChild : public StaticParent {
void foo();
}
StaticChild sc;
sc.foo(); // calls StaticChild::foo
StaticParent &sp = sc;
sp.foo(); // calls StaticParent::foo
struct VirtualParent {
virtual void foo();
};
struct VirtualChild : public VirtualParent {
virtual void foo();
}
VirtualChild vc;
vc.foo(); // calls VirtualChild::foo
VirtualParent &vp = vc;
vp.foo(); // calls VirtualChild::foo
Yes, this is valid C++ syntax and will define a Child::func1 which hides Parent::func1 in Child.
However, this does not mean that it fully replaces Child::Parent::func1. This function can still be called explicitly on an element of child.
Child c;
c.Parent::func1();
Also, this function will not be virtual. Thus, the following..
Child c;
Parent& p = c;
p.func1();
will call Parent::func1 and not Child::func1.
Most has been said.
Your expectations would be right if you talk about java. In java any non-private, non-final method could be overridden. Maybe you are more familiar with an other programming language than C++
By the way, two things are wrong in your code
"class" must be written lower case
the default access of members in class is "private". It is NOT allowed nor useful to override private members which are non-pure
I have one base class which holds a map for function pointers like this
typedef void (BaseClass::*event_t)();
class BaseClass {
protected:
std::map<std::string, event_t> events;
public:
// Example event
void onFoo() {
// can be added easily to the map
}
};
Handling this works prefect, but now i want to make BaseClass an abstract base class to derive from like this:
class SpecificClass : public BaseClass {
public:
void onBar() {
// this is gonna be difficult!
}
};
Although i can access the map from SpecificClass i am not able to add onBar because the event_t type is only defined for the BaseClass! Is there any possibility (maybe with templates?) which does not lead to define the event_t for each class i will use...
(It is not neccessary to use templates! Any good/suitable approach would be nice.)
More background information:
This whole thing is for a text based RPG. My base class could be called Location and the specifc one any location e.g. CivicCenter. Each Location object subscribes to my EventSystem which notifies all neccessary objects when i fire an event. Therefore i want to store in a map some pointers to private functions holding the actions with their "name" like onSetOnFire (xD) as the key.
This can't be done with your current map as it stands. Think about what would happen if you could put a child method into the map. Then you could pull a pointer-to-child-member (masquerading as base) out of the map, call it on a base class instance pointer, and then how would it call a derived class on a base class instance which obviously couldn't work.
Would a polymorphic approach work?
Yes; stop using member pointers.
The more correct way of doing what you want is to have an event type and an object pointer. So an event fires on a specific object. The event type would be a non-member function (or a static member). It would be passed the object pointer. And it would call some actual member function of that object.
Nowadays, the event type could be a std/boost::function. However, since the function parameters have to stay the same type for all events, this doesn't really fix your problem. You can't call SpecificClass::onBar from a BaseClass pointer unless you do a cast to a SpecificClass. And the event calling function would not know to do this. So you still can't put SpecificClass::onBar in the std/boost::function object; you still need some standalone function to do the cast for you.
This all just seems to be a terrible use of polymorphism. Why does SpecificClass need to derive from BaseClass at all? Can't they just be two unrelated classes?
You have to use static_cast:
event_t evt = static_cast<event_t>(&SpecificClass::onBar);
This is because it is slightly dangerous to cast to event_t, you could accidently apply it to a BaseClass instance.
How it works (for the skeptical):
class BaseClass {
public:
typedef void (BaseClass::*callback_t)(); // callback method
void doSomething(callback_t callback) {
// some code
this->*callback();
// more code
}
void baseCallback(); // an example callback
};
class DerivedClass : public BaseClass {
public:
void derivedCallback();
void doWhatever() {
// some code
doSomething(&BaseClass::baseCallback);
// more code
doSomething(static_cast<callback_t>(&DerivedClass::derivedCallback));
// et cetera
};
Here is what you should avoid, and why this is potentially dangerous:
void badCodeThatYouShouldNeverWrite()
{
BaseClass x;
// DO NOT DO THIS IT IS BAD
x.doSomething(static_cast<callback_t>(&DerivedClass::derivedCallback));
}
The requirement for a static_cast makes it so you can't "accidentally" pass DerivedClass method pointers in. And if you think this is dangerous, just remember that it's a pointer, and pointers are always dangerous. Of course, there are ways you can do this that involve creating helper classes, but that requires a lot of extra code (possibly making a class for every function you want to pass as a callback). Or you could use closures in C++11, or something from Boost, but I realize that a lot of us do not have that option.
After some thought and a redesign i was able to achieve what i wanted. Although i am stubborn and still using inheritance i have reimplemented the map. This is how it works now:
class Location {
// ...
protected:
std::map<std::string, std::function<void(void)>> m_mEvents;
};
And now i can handle it like this:
class CivicCenter : public Location {
public:
CivicCenter() {
// this is done by a macro which lookes better than this
this->m_mEvents["onTriggerSomething"] =
std::bind(&CivicCenter::onTriggerSomething, this);
}
void onTriggerSomething() {
// ...
}
// ...
};
With easy use of std::bind i am able to implement generic function pointers. When using parameters like in std::function<void(int, int)> remeber to use either boost's _1 and _2 or lambda expressions like me:
std::function<void(int,int)> f = [=](int a, int b) {
this->anotherFunctionWithParams(a, b);
};
But this is just pointed out due to completeness of my solution.
I am trying to make a call to a Parent class method from a contained object, but have no luck with the following code. What is the standard way to do it?
I have searched around and this seems to work for inherited objects, but not for contained objects. Is it right to call it a Parent class even? Or is it called an Owner class?
class Parent{
private:
Child mychild;
public:
void doSomething();
}
class Child{
public:
void doOtherThing();
}
void Child::doOtherThing(){
Parent::doSomething();
}
A contained object has no special access to the class that contains it, and in general does not know that it is contained. You need to pass a reference or a pointer to the containing class somehow - for example:
class Child{
public:
void doOtherThing( Parent & p );
};
void Child::doOtherThing( Parent & p ){
p.doSomething();
}
The child has no connection to the parent class at all. You'll have to pass 'this' down to the child (probably in the constructors) to make this work.
If the child needs to interact with the parent, then it will need a reference to that object; at present, the child has no notion of an owner.