I got class called CharacterAnimation consists of one virtual method:
CharacterAnimation : public cocos2d::CCObject {
public:
...
virtual void start(float td);
}
and several inherited from it classes:
CharacterAnimationBlink
CharactedAnimationDropTear
etc
What I want is:
Create
std::map<std::string, CharacterAnimation*> animationsList;
Fill animationList like:
animationsList["blink"] = new CharacterAnimationBlink(1,2,3);
animationsList["dropTear"] = new CharacterAnimationDropTear(1,2);
Looping through this std::map
For each std::map element call
this->schedule(schedule_selector(characterAnimationStartMethodPointer), Character::animationPeriod);
What should be placed instead of currentAnimationStartMethodPointer? How do I access a pointer to start() method of current object from std::map?
From CCObject.h
typedef void (CCObject::*SEL_SCHEDULE)(float);
...
#define schedule_selector(_SELECTOR) (SEL_SCHEDULE)(&_SELECTOR)
Assuming that you don't control the declaration for the schedule() function, you can't get a single pointer to the start() function of a particular CharacterAnimation instance. Instead, you need two things here: a member function pointer, and a reference or pointer to the instance upon which that function should be called.
As presented in your question, it looks like schedule() demands a member function pointer (in particular, a function from the CCObject class). Your CharacterAnimation class inherits from CCObject, but a member function pointer to CharacterAnimation::start() is not a member function pointer to a CCObject function, assuming from the lack of a virtual or override specifier that start() is declared in CharacterAnimation and not inherited from CCObject.
Use this code to get the global scheduler to call the start method every Character::animationPeriod seconds.
for (std::map<std::string, CharacterAnimation*>::iterator i = animationsList.begin();
i != animationsList.end();
++i)
{
CCDirector::sharedDirector()->getScheduler()->scheduleSelector(schedule_selector(CharacterAnimation::start),
i->second,
Character::animationPeriod,
false);
}
Related
Here are my code
#include <iostream>
using namespace std;
class BaseClass
{
public:
BaseClass() {}
void init(const int object) { cout<<"BaseClass::init"<<endl; }
void run(const int object) { cout<<"BaseClass::run calls =>"; init(object); }
};
class Derived : public BaseClass {
public:
Derived() {}
void init(const int object) { cout<<"Derived::init"<<endl; }
};
int main() {
BaseClass b;
b.init('c');
b.run('c');
Derived d;
d.init(5); // Calls Derived::init
d.run(5); // Calls Base::init. **I expected it to call Derived::init**
}
And here is generated output
BaseClass::init
BaseClass::run calls =>BaseClass::init
Derived::init
BaseClass::run calls =>BaseClass::init
With call d.run(5), Why "BaseClass::init" is being called instead of "Derived::init" ?
I though we need virtual functions only when calling through a pointer.
What is the rationale behind keeping such behavior ?
Why "BaseClass::init" is being called instead of "Derived::init" ?
Because init is a non-virtual member function. To have the desired effect, you need to make init a virtual member function as shown below:
class BaseClass
{
public:
BaseClass() {}
//NOTE THE VIRTUAL KEYWORD HERE
virtual void init(const int object) { cout<<"BaseClass::init"<<endl; }
//other member function here as before
};
Demo
I though we need virtual functions only when calling through a pointer.
Note that the statement init(object); is equivalent to writing
this->init(object); //here `this` is a pointer
When you wrote:
d.run(5);
In the above statement, first the address of object d is implicitly passed as the first argument to the implicit this parameter of member function run. The type of this implicit this parameter is BaseClass* and this happens due to derived to base conversion. Now, the call init(object); is equivalent to this->init(object);. But since init is a non-virtual member function, the call is resolved at compile time meaning the base class init will be called.
Basically when a member function is called with a derived class object, the compiler first looks to see if that member exists in the derived class. If not, it begins walking up the inheritance chain and checking whether the member has been defined in any of the parent classes. It uses the first one it finds. This means for the call d.run(5) the search for a member function named run starts inside the derived class. But since there is no function named run inside derived class, the compiler looks into the direct base class BaseClass and finds the member function named run. So it stops its search and uses this found run member function. And as i said, in your example, init is non-virtual and so the call is resolved at compile time to the base class run.
On the other hand, if we make init to be a virtual member function, then this call will be resolved at run-time meaning the derived class init will be called.
I though we need virtual functions only when calling through a pointer.
No. Thats not right. You need to make a function virtual when you want to enable calling it based on the dynamic type of the object. And once you do have a virtual function you can use pointers or references to make use of the virtual dispatch.
You need to make a method virtual when you want to override it. As BaseClass::run is not overridden by Derived::run, there is no virtual dispatch and calling init from BaseClass::run calls BaseClass::init. If you want to enable virtual dispatch for BaseClass::init you need to declare it virtual.
Further, consider that your code is equivalent to:
void run(const int object) {
cout<<"BaseClass::run calls =>";
this->init(object);
}
this is BaseClass*, hence BaseClass::init is called. You are calling init via a pointer, but that does not matter because init is not virtual. If you want to call init based on the dynamic type of the object, thats exactly what virtual is good for. The "overhead" you refer to in comments is not really overhead, but just the minimum needed to get the behavior you want. If you can change the design and do not need runtime polymorphism you can take a look at CRTP wich is a form of static polymorphism.
I need to pass an object's static method as callback function using following code:
glutDisplayFunc(callback)
Where callback is a static method of some class - baseClass::callback(). It compiles fine. But now I want to have a derived class (having baseClass as it's parent) having the same callback function - that is, I want to overwrite the callback function.
I've overwritten it in derivedClass but derivedClass::callback() is not getting called.
PS. I'm calling glutDisplayFunc(callback) withing the base class. Code looks like:
baseClass::someFunction(){
glutDisplayFunc(callback);
}
How do I pass derivedClass::callback instead of baseClass::callback withing a method of baseClass? All methods are static.
C++ does not support virtual static methods, so you can't do what you're trying to do directly. What you should be able to do is create a non-static virtual method that returns a function pointer, and override that in your derived class to return a pointer to it's static callback method.
i.e. something like this:
class A
{
public:
typedef void(*CallbackFunction)(void);
public:
static void callback(void)
{
std::cout << "A::callback" << std::endl;
}
virtual CallbackFunction getCallback()
{
return callback;
}
void someFunction()
{
glutDisplayFunc(getCallback());
}
};
class B: public A
{
public:
static void callback(void)
{
std::cout << "B::callback" << std::endl;
}
CallbackFunction getCallback()
{
return callback;
}
};
Not exactly ideal, but it's a decent workaround for C callbacks that don't support context parameters.
The short answer is that you can't, and furthermore you generally don't want to. A base class generally shouldn't have direct knowledge of specific derived functions.
The usual pattern for this is to have a static function in the base class that invokes a virtual function, then override the virtual function in the derived class. I'm not sure if that applies here though -- to work, you need to be able to get a parameter passed to the callback function. The parameter you pass is a pointer to the object, so you cast that back to the base object type, then invoke the correct virtual function off of that pointer.
In the specific case of glutDisplayFunc, however, I don't believe that's possible -- it doesn't allow you to get a parameter passed to the callback function. I'm afraid there is no real cure other than to switch to something other than GLUT if you want to do this style of programming.
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'm having a little problem with inheritance in C++ that I can't quite figure out.
So, say I have some classes derived from stl list, i.e:
class Class1: public list<T>{
virtual func1();
}
class Class2 : public Class1<w/e>{
func1();
}
The problem I'm having is when passing these to a function. How can I properly pass an instance of one of these to a function so that it will use the proper virtual function if it is possible for an instance of either type to be passed? I haven't done inheritance and virtual functions in awhile so I am a bit rusty here.
(This assuming that the function is not a member function of the classes).
You will need to pass them to the function as a reference
int function(Class1& obj);
or as a pointer;
int function(Class1* obj);
and it should just plain call the correct version of the virtual method.
If you pass them without either of those
int function(Class1 obj);
The object will be copy constructed to always be a Class1 in the function, and will always call Class1::func1()
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.