473,397 Members | 1,949 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,397 software developers and data experts.

Double dispatch (makes no sense!)

I am trying to use double dispatch in the below code:

#include <iostream>

class Box;
class Sphere;
class geometry_type
{
public:
virtual void haps(geometry_type* other)=0;
virtual void collideWith(Box* other)=0;
virtual void collideWith(Sphere* other) = 0;
};

class Box : public geometry_type
{
public :
Box() {}

virtual void haps(geometry_type* other)
{
other->collideWith(this);
}

virtual void collideWith(Sphere* other) {
std::cout << "Sphere collision with Sphere" << std::endl;
}

virtual void collideWith(Box* other) {
std::cout << "Box collision with Box" << std::endl;
}
};

class Sphere : public geometry_type
{
public :
Sphere() {}

virtual void haps(geometry_type* other)
{
other->collideWith(this);
}

virtual void collideWith(Sphere* other) {
std::cout << "Sphere collision with Sphere" << std::endl;
}

virtual void collideWith(Box* other) {
std::cout << "Sphere collision with Box" << std::endl;
}
};
void narrow_phase(geometry_type* G1, geometry_type* G2)
{
G1->haps(G2);
}

int main()
{
Box* BoxA = new Box();
Sphere* SphereA = new Sphere();

BoxA->collideWith(BoxA);
SphereA->collideWith(BoxA);

// Should print box collide with box.
narrow_phase(BoxA, BoxA);

// Should print sphere collide with box.
narrow_phase(SphereA, BoxA);

// Should print box collide with sphere.
narrow_phase(BoxA, SphereA);

return 0;

}
But when I run main I get:

Box collision with Box
Sphere collision with Box
Box collision with Box
Sphere collision with Sphere
Sphere collision with Box
What goes on in the last two calls?
Jun 27 '08 #1
6 1334
saneman wrote:
...
class Box : public geometry_type
{
public :
Box() {}

virtual void haps(geometry_type* other)
{
other->collideWith(this);
}

virtual void collideWith(Sphere* other) {
std::cout << "Sphere collision with Sphere" << std::endl;
Huh? This should be "Box collision with Sphere", shouldn't it?
}

virtual void collideWith(Box* other) {
std::cout << "Box collision with Box" << std::endl;
}
};

class Sphere : public geometry_type
{
public :
Sphere() {}

virtual void haps(geometry_type* other)
{
other->collideWith(this);
}

virtual void collideWith(Sphere* other) {
std::cout << "Sphere collision with Sphere" << std::endl;
}

virtual void collideWith(Box* other) {
std::cout << "Sphere collision with Box" << std::endl;
}
};
void narrow_phase(geometry_type* G1, geometry_type* G2)
{
G1->haps(G2);
}

int main()
{
Box* BoxA = new Box();
Sphere* SphereA = new Sphere();

BoxA->collideWith(BoxA);
SphereA->collideWith(BoxA);

// Should print box collide with box.
narrow_phase(BoxA, BoxA);

// Should print sphere collide with box.
narrow_phase(SphereA, BoxA);
No. Your 'haps' method essentially "swaps" the objects involved in the
collision (take a closer look at it): 'G1' from 'narrow_phase' becomes
'this' in 'haps'. So, it should print "Box collision with Sphere". And
it will, if you fix the error mentioned above.
// Should print box collide with sphere.
narrow_phase(BoxA, SphereA);
Again, no. For the very same reason it should print "Sphere collision
with Box". And that exactly what it prints.
return 0;

}
But when I run main I get:

Box collision with Box
Sphere collision with Box
Box collision with Box
Sphere collision with Sphere
Sphere collision with Box
What goes on in the last two calls?
See above.

--
Best regards,
Andrey Tarasevich
Jun 27 '08 #2
saneman wrote:
I am trying to use double dispatch in the below code:

#include <iostream>

class Box;
class Sphere;
class geometry_type
{
public:
virtual void haps(geometry_type* other)=0;
virtual void collideWith(Box* other)=0;
virtual void collideWith(Sphere* other) = 0;
};

class Box : public geometry_type
{
[...]
virtual void collideWith(Sphere* other) {
std::cout << "Sphere collision with Sphere" << std::endl;
Are you sure this output reflects the actual pairing of the
types here?
}
};
[..]

What goes on in the last two calls?
Instead of looking at debug printouts, step through your code
in a debugger to make sure the correct function is called.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jun 27 '08 #3

>I am trying to use double dispatch in the below code:

#include <iostream>

class Box;
class Sphere;
class geometry_type
{
public:
virtual void haps(geometry_type* other)=0;
virtual void collideWith(Box* other)=0;
virtual void collideWith(Sphere* other) = 0;
};

class Box : public geometry_type
{
public :
Box() {}

virtual void haps(geometry_type* other)
{
other->collideWith(this);
}

virtual void collideWith(Sphere* other) {
std::cout << "Sphere collision with Sphere" << std::endl;
}
Here is a typo;it should read' Box collision with sphere'

virtual void collideWith(Box* other) {
std::cout << "Box collision with Box" << std::endl;
}
};

class Sphere : public geometry_type
{
public :
Sphere() {}

virtual void haps(geometry_type* other)
{
other->collideWith(this);
}

virtual void collideWith(Sphere* other) {
std::cout << "Sphere collision with Sphere" << std::endl;
}

virtual void collideWith(Box* other) {
std::cout << "Sphere collision with Box" << std::endl;
}
};
void narrow_phase(geometry_type* G1, geometry_type* G2)
{
G1->haps(G2);
}

int main()
{
Box* BoxA = new Box();
Sphere* SphereA = new Sphere();

BoxA->collideWith(BoxA);
SphereA->collideWith(BoxA);

// Should print box collide with box.
narrow_phase(BoxA, BoxA);

// Should print sphere collide with box.
narrow_phase(SphereA, BoxA);

// Should print box collide with sphere.
narrow_phase(BoxA, SphereA);

return 0;

}
But when I run main I get:

Box collision with Box
Sphere collision with Box
Box collision with Box
Sphere collision with Sphere
Sphere collision with Box
What goes on in the last two calls?
Last one is correct, you switch the parameters
inside the haps. Late there :)
Jun 27 '08 #4
saneman wrote:
I am trying to use double dispatch in the below code:

#include <iostream>

class Box;
class Sphere;
class geometry_type
{
public:
virtual void haps(geometry_type* other)=0;
virtual void collideWith(Box* other)=0;
virtual void collideWith(Sphere* other) = 0;
};

class Box : public geometry_type
{
public :
Box() {}

virtual void haps(geometry_type* other)
{
other->collideWith(this);
}

virtual void collideWith(Sphere* other) {
std::cout << "Sphere collision with Sphere" << std::endl;
}

virtual void collideWith(Box* other) {
std::cout << "Box collision with Box" << std::endl;
}
};

class Sphere : public geometry_type
{
public :
Sphere() {}

virtual void haps(geometry_type* other)
{
other->collideWith(this);
}

virtual void collideWith(Sphere* other) {
std::cout << "Sphere collision with Sphere" << std::endl;
}

virtual void collideWith(Box* other) {
std::cout << "Sphere collision with Box" << std::endl;
}
};
void narrow_phase(geometry_type* G1, geometry_type* G2)
{
G1->haps(G2);
}

int main()
{
Box* BoxA = new Box();
Sphere* SphereA = new Sphere();

BoxA->collideWith(BoxA);
SphereA->collideWith(BoxA);

// Should print box collide with box.
narrow_phase(BoxA, BoxA);

// Should print sphere collide with box.
narrow_phase(SphereA, BoxA);

// Should print box collide with sphere.
narrow_phase(BoxA, SphereA);

return 0;

}
But when I run main I get:

Box collision with Box
Sphere collision with Box
Box collision with Box
Sphere collision with Sphere
Sphere collision with Box
What goes on in the last two calls?
Because your Box::collideWith(Sphere*) has a bug in it. Has nothing to
do with your double dispatch, which appears to be working perfectly.


--
Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
Jun 27 '08 #5
hurcan solter wrote:
>
>I am trying to use double dispatch in the below code:

#include <iostream>

class Box;
class Sphere;
class geometry_type
{
public:
virtual void haps(geometry_type* other)=0;
virtual void collideWith(Box* other)=0;
virtual void collideWith(Sphere* other) = 0;
};

class Box : public geometry_type
{
public :
Box() {}

virtual void haps(geometry_type* other)
{
other->collideWith(this);
}

virtual void collideWith(Sphere* other) {
std::cout << "Sphere collision with Sphere" << std::endl;
}
Here is a typo;it should read' Box collision with sphere'

> virtual void collideWith(Box* other) {
std::cout << "Box collision with Box" << std::endl;
}
};

class Sphere : public geometry_type
{
public :
Sphere() {}

virtual void haps(geometry_type* other)
{
other->collideWith(this);
}

virtual void collideWith(Sphere* other) {
std::cout << "Sphere collision with Sphere" << std::endl;
}

virtual void collideWith(Box* other) {
std::cout << "Sphere collision with Box" << std::endl;
}
};
void narrow_phase(geometry_type* G1, geometry_type* G2)
{
G1->haps(G2);
}

int main()
{
Box* BoxA = new Box();
Sphere* SphereA = new Sphere();

BoxA->collideWith(BoxA);
SphereA->collideWith(BoxA);

// Should print box collide with box.
narrow_phase(BoxA, BoxA);

// Should print sphere collide with box.
narrow_phase(SphereA, BoxA);

// Should print box collide with sphere.
narrow_phase(BoxA, SphereA);

return 0;

}
But when I run main I get:

Box collision with Box
Sphere collision with Box
Box collision with Box
Sphere collision with Sphere
Sphere collision with Box
What goes on in the last two calls?

Last one is correct, you switch the parameters
inside the haps. Late there :)
thanks! Yes it was a bit late :-) I am wondering why the baseclass
should be declared as abstract. I have tried to change it to:
class geometry_type
{
public:

virtual void haps(geometry_type* other)
{
other->collideWith(this);
}
virtual void collideWith(Box* other)
{
std::cout << "Box collision" << std::endl;
}

virtual void collideWith(Sphere* other)
{
std::cout << "Sphere collision" << std::endl;
}

// virtual void haps(geometry_type* other)=0;
// virtual void collideWith(Box* other)=0;
// virtual void collideWith(Sphere* other) = 0;

};

But then I get:
test2.cpp: In member function ‘virtual void
geometry_type::haps(geometry_type*)’:
test2.cpp:16: error: no matching function for call to
‘geometry_type::collideWith(geometry_type* const)’
test2.cpp:19: note: candidates are: virtual void
geometry_type::collideWith(Box*)
test2.cpp:24: note: virtual void
geometry_type::collideWith(Sphere*)
Is there some rule that the baseclass must be abstract?
Jun 27 '08 #6
On May 9, 10:42 am, saneman <d...@sdf.comwrote:
hurcan solter wrote:
thanks! Yes it was a bit late :-) I am wondering why the baseclass
should be declared as abstract.
It doesn't have to be.
I have tried to change it to:

class geometry_type
{
public:
virtual void haps(geometry_type* other)
{
other->collideWith(this);
And what should this call? Function overload resolution only
concerns static types.
}
virtual void collideWith(Box* other)
{
std::cout << "Box collision" << std::endl;
}
virtual void collideWith(Sphere* other)
{
std::cout << "Sphere collision" << std::endl;
}
// virtual void haps(geometry_type* other)=0;
// virtual void collideWith(Box* other)=0;
// virtual void collideWith(Sphere* other) = 0;
};
But then I get:

test2.cpp: In member function ?virtual void
geometry_type::haps(geometry_type*)?:
test2.cpp:16: error: no matching function for call to
?geometry_type::collideWith(geometry_type* const)?
test2.cpp:19: note: candidates are: virtual void
geometry_type::collideWith(Box*)
test2.cpp:24: note: virtual void
geometry_type::collideWith(Sphere*)
Is there some rule that the baseclass must be abstract?
No. But there is a rule that when you call a function, one of
the function found with name lookup must be callable with the
static types of your arguments.

Think about it for a moment. What you're asking for is
basically double dispatch. Or at least, dispatch on the dynamic
type of an argument, not on the object the function is called
on.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jun 27 '08 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: Thomas Matthews | last post by:
Hi, I'm looking for an efficient method to deep copy containers of fields. A Field is a parent class with children such as Integer_Field, String_Field, and Date_Field, etc. The algorithm /...
45
by: Debashish Chakravarty | last post by:
K&R pg.66 describes two situations when using goto makes sense. Has anyone here come across situations where using goto provided the most elegant solution. --...
3
by: Dan Vogel | last post by:
I'd like to find an elegant solution to the problem of calling a certain function based on the types of two parameters. In my case, the functions compute the distance between different types of...
3
by: Developer.Man4 | last post by:
Hi all, i've been investigating for quite a while for files that are mandatory to be deployed to the server for an asp.net v1.1 application to run, to make it more clear, we don't need to move...
5
by: yoni | last post by:
Hi, I am trying to write a regexp to find all the code on the header of entities in SQL Server (views, SPs, etc...) I got something like this: (.|\n)*((create view)|(create proc)|(create...
0
by: learning | last post by:
hi, is there a way to make a function dispatch table in C#? Purpose: I have am using Microsoft web test to automate web testing. the web test generated are all a collection declarative...
2
by: DeMarcus | last post by:
Since I started with OO I've been told switching on typeid is a big no-no. E.g. void Washer::wash( Vehicle myVehicle ) { if( typeid(myVehicle) == typeid(Car) ) Washer::washCar( myVehicle );...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.