class A
{
int y;
public:
virtual void vfunc(A &other)
{
cout << "called A's vfunc()" << endl;
}
};
class B : public virtual A
{
public:
virtual void vfunc(C &other)
{
cout << "called B's vfunc()" << endl;
}
};
class C : public virtual A
{
public:
virtual void vfunc(D &other)
{
cout << "called C's vfunc()" << endl;
}
};
class D : public B,public C
{
public:
virtual void vfunc(D &other)
{
cout << "called D's vfunc()" << endl;
}
};
int main (int argc, char **argv)
{
vector <A *> array;
A* ptr;
A aObj;
B bObj;
C cObj;
D dObj;
ptr = &aObj;
array.push_back(ptr);
ptr = &bObj;
array.push_back(ptr);
ptr = &cObj;
array.push_back(ptr);
ptr = &dObj;
array.push_back(ptr);
for (int i = 0; i < 3; i++)
{
//*array always dereferences to an object of type A, regardless of declared type
//And therefore always calls A::vfunc(A &other)
array->vfunc(*array);
}
return 0;
}
Inheritance issue
Hello, first time posting on here and I'm definately no coding guru. Here's to hoping I don't make a fool of myself.
I am trying to store pointers to various base and derived objects mixed together in a vector, and then call a virtual function based with a dereferenced pointer (from that same vector) as the parameter.
If the above run-on sentence is confusing just look below for a general implementation of the problem I'm having (see comment in for loop):
current output in std::cout:
called A's vfunc()
called A's vfunc()
called A's vfunc()
called A's vfunc()
intended output:
called A's vfunc()
called B's vfunc()
called C's vfunc()
called D's vfunc()
After running into the problem, I now see that the problem is that the virtual functions... uhhhhh... virtualness isn't doing any good here - it might as well be just normal overloaded functions. The best solution for me would be if there were some easy way to dereference the pointer back to it's original type (and thus vfunc() would have the correct parameter).
If you want to know why I want the above problem to be solved - read on:
I have a collision detector class with an array of collision sprite pointers. The detector has a function, resolveCollisions(), which would iterate through all possible combinations of sprites (not permutations) and test for a collision with each combination. If a collision was detected, then each collidable object is told to adjust itself accordingly given the object with which it is colliding.
For example, if the ball collides with the goal - then the ball needs to reset and the player scores. If the ball collides with anything else - use the default collision handling.
So if you have a better way for me to harvest and/or handle collisions - I would be more than gratful for you to enlighten me.
None of the vfunc functions in the derived classes have the same parameter as vfunc in the base class. You can't both override and overload a function. Make all the parameters the same.
I'm not sure if I understand, but here is how one might go about an interface.
class CBase
{
public:
virtual void MyFunc( void ) = 0;
};
class COne : public CBase
{
public:
void MyFunc( void ){ printf("COne function\n");}
};
class CTwo : public CBase
{
public:
virtual void MyFunc( void ){ printf("CTwo function\n");}
};
class CThree : public CTwo
{
public:
void MyFunc( void ){ printf("CThree function\n");}
};
int _tmain(int argc, _TCHAR* argv[])
{
CBase* pInterface;
COne one;
CTwo two;
CThree three;
pInterface = &one
pInterface->MyFunc();
pInterface = &two
pInterface->MyFunc();
pInterface = &three
pInterface->MyFunc();
return 0;
}
class CBase
{
public:
virtual void MyFunc( void ) = 0;
};
class COne : public CBase
{
public:
void MyFunc( void ){ printf("COne function\n");}
};
class CTwo : public CBase
{
public:
virtual void MyFunc( void ){ printf("CTwo function\n");}
};
class CThree : public CTwo
{
public:
void MyFunc( void ){ printf("CThree function\n");}
};
int _tmain(int argc, _TCHAR* argv[])
{
CBase* pInterface;
COne one;
CTwo two;
CThree three;
pInterface = &one
pInterface->MyFunc();
pInterface = &two
pInterface->MyFunc();
pInterface = &three
pInterface->MyFunc();
return 0;
}
A common way to solve your problem is by doing something called "double dispatch". It is related to the Visitor design pattern. The following code demonstrates how it works:
It's a little complicated, but here's how it works. Suppose you have 2 objects:
Double dispatch is not pretty, especially because every time you add another class you must add a function to every class. The advantage is that it is pretty fast because everything is resolved at compile time. The alternative is to have a map of collision functions whose key a pair of collidable types and every collision permutation (along with the function to test the collision) is registered in the map. Then it is a simple lookup to determine which collision function to call.
class Collidable { public: virtual bool Collides( Collidable const *pX ) const = 0; virtual bool Collides( A const & a ) const = 0; virtual bool Collides( B const & b ) const = 0; virtual bool Collides( C const & c ) const = 0; protected: // Implement these to do the actual detection (1 for every combination) static bool Collides( A const & a1, A const & a2 ); static bool Collides( A const & a, B const & b ); static bool Collides( A const & a, C const & c ); static bool Collides( B const & b1, B const & b2 ); static bool Collides( B const & b, C const & c ); static bool Collides( C const & c1, C const & c2 ); }; class A : public Collidable { virtual bool Collides( Collidable const *pX ) const { return pX->Collides( *this ); } virtual bool Collides( A const & a ) const { return Collides( *this, a ); } virtual bool Collides( B const & b ) const { return Collides( *this, b ); } virtual bool Collides( C const & c ) const { return Collides( *this, c ); } }; // Implement similar code for B and C.
It's a little complicated, but here's how it works. Suppose you have 2 objects:
A a; B b; Collidable * x1 = &b Collidable * x2 = &a
To test for collision, you simply call x1->Collides( x2 );
That calls B::Collides( Collidable const *pX ). Since pX here points to an A, the function A::Collides( B const & b ) is called. This function calls A::Collides( A const & a, B const & b ), which does the actual collision detection.Double dispatch is not pretty, especially because every time you add another class you must add a function to every class. The advantage is that it is pretty fast because everything is resolved at compile time. The alternative is to have a map of collision functions whose key a pair of collidable types and every collision permutation (along with the function to test the collision) is registered in the map. Then it is a simple lookup to determine which collision function to call.
Quote:Original post by JohnBolton
None of the vfunc functions in the derived classes have the same parameter as vfunc in the base class. You can't both override and overload a function. Make all the parameters the same.
Thanks for the info, and especially thank you for the double dispatch thing. It's all greatly appreciated.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement