Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > "Virtual functions allow polymorphism on a single argument" ?

Reply
Thread Tools

"Virtual functions allow polymorphism on a single argument" ?

 
 
desktop
Guest
Posts: n/a
 
      05-10-2007
This page:

http://www.eptacom.net/pubblicazioni/pub_eng/mdisp.html

start with the line: "Virtual functions allow polymorphism on a single
argument". What does that exactly mean?

I guess it has nothing to do with making multiple arguments in a
declaration like:

virtual void setId(int a, int b) {id = a+b;}
 
Reply With Quote
 
 
 
 
Alf P. Steinbach
Guest
Posts: n/a
 
      05-10-2007
* desktop:
> This page:
>
> http://www.eptacom.net/pubblicazioni/pub_eng/mdisp.html
>
> start with the line: "Virtual functions allow polymorphism on a single
> argument". What does that exactly mean?
>
> I guess it has nothing to do with making multiple arguments in a
> declaration like:
>
> virtual void setId(int a, int b) {id = a+b;}


Right. The argument in question is the implicit this-pointer, the
object you're calling the member function on. And what it means is that
what member function implementation to call is selected based on the run
time type of that argument.

Polymorphism on two or more arguments is difficult because the number of
possible function implementations is then the product of the number of
possible classes for each argument.

One useful technique is known as double dispatch; look it up.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
 
Reply With Quote
 
 
 
 
Victor Bazarov
Guest
Posts: n/a
 
      05-10-2007
desktop wrote:
> This page:
>
> http://www.eptacom.net/pubblicazioni/pub_eng/mdisp.html
>
> start with the line: "Virtual functions allow polymorphism on a single
> argument". What does that exactly mean?
>
> I guess it has nothing to do with making multiple arguments in a
> declaration like:
>
> virtual void setId(int a, int b) {id = a+b;}


Sort of. The "single argument" relates to the polymorphism based on the
object itself -- difference in behaviours depending on the dynamic (or
the creation) class of the object. This is (if you read further) put
in opposition to "multi-argument polymorphism" where the behaviour of
a pair of objects should be specific, IOW, along with the object itself
you need to involve the actual explicit argument in defining the
behaviour.

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


 
Reply With Quote
 
desktop
Guest
Posts: n/a
 
      05-10-2007
Alf P. Steinbach wrote:
> * desktop:
>> This page:
>>
>> http://www.eptacom.net/pubblicazioni/pub_eng/mdisp.html
>>
>> start with the line: "Virtual functions allow polymorphism on a single
>> argument". What does that exactly mean?
>>
>> I guess it has nothing to do with making multiple arguments in a
>> declaration like:
>>
>> virtual void setId(int a, int b) {id = a+b;}

>
> Right. The argument in question is the implicit this-pointer, the
> object you're calling the member function on. And what it means is that
> what member function implementation to call is selected based on the run
> time type of that argument.


Ok so the argument in question is "obj" in this context:

obj.callMe()

where obj is the object that the member function "callMe()" is called upon.

Since obj can be an instance of B,C or D (if they are all descendants
from a base class A) it is first at runtime it is decided which (B, C or
D) "callme()" function will be run.


> Polymorphism on two or more arguments is difficult because the number of
> possible function implementations is then the product of the number of
> possible classes for each argument.



But how can there be more than one object that a function is called
upon? As I see it there can only be one (like obj) but it might differ
at runtime which type it is.


> One useful technique is known as double dispatch; look it up.


I am currently reading this pattern but need to understand what they
mean with polymorphism with one or two arguments.
 
Reply With Quote
 
Rolf Magnus
Guest
Posts: n/a
 
      05-11-2007
desktop wrote:

> Alf P. Steinbach wrote:
>> * desktop:
>>> This page:
>>>
>>> http://www.eptacom.net/pubblicazioni/pub_eng/mdisp.html
>>>
>>> start with the line: "Virtual functions allow polymorphism on a single
>>> argument". What does that exactly mean?
>>>
>>> I guess it has nothing to do with making multiple arguments in a
>>> declaration like:
>>>
>>> virtual void setId(int a, int b) {id = a+b;}

>>
>> Right. The argument in question is the implicit this-pointer, the
>> object you're calling the member function on. And what it means is that
>> what member function implementation to call is selected based on the run
>> time type of that argument.

>
> Ok so the argument in question is "obj" in this context:
>
> obj.callMe()
>
> where obj is the object that the member function "callMe()" is called
> upon.


obj must be a reference, otherwise there is no polymorphism.

> Since obj can be an instance of B,C or D (if they are all descendants
> from a base class A) it is first at runtime it is decided which (B, C or
> D) "callme()" function will be run.
>
>
>> Polymorphism on two or more arguments is difficult because the number of
>> possible function implementations is then the product of the number of
>> possible classes for each argument.

>
>
> But how can there be more than one object that a function is called
> upon? As I see it there can only be one (like obj) but it might differ
> at runtime which type it is.



Right, and that's exactly the reason why this is "polymorphism on a single
argument".

>> One useful technique is known as double dispatch; look it up.

>
> I am currently reading this pattern but need to understand what they
> mean with polymorphism with one or two arguments.


It simply means that the function that is seleccted at runtime depends on
the dynamic type of one or two objects.

 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      05-11-2007
On May 11, 12:07 am, desktop <(E-Mail Removed)> wrote:
> Alf P. Steinbach wrote:
> > * desktop:
> >> This page:


> >>http://www.eptacom.net/pubblicazioni/pub_eng/mdisp.html


> >> start with the line: "Virtual functions allow polymorphism on a single
> >> argument". What does that exactly mean?


> >> I guess it has nothing to do with making multiple arguments in a
> >> declaration like:


> >> virtual void setId(int a, int b) {id = a+b;}


> > Right. The argument in question is the implicit this-pointer, the
> > object you're calling the member function on. And what it means is that
> > what member function implementation to call is selected based on the run
> > time type of that argument.


> Ok so the argument in question is "obj" in this context:


> obj.callMe()


> where obj is the object that the member function "callMe()" is called upon.


Yes. In C++ syntax. Conceptually, this can be mapped to
callMe( obj ), with polymorphism always occuring on the first
object (in C++).

Now consider something like "obj.callMe( arg )". Conceptually,
this would be "callMe( obj, arg )". In C++, polymorphism only
works on the first argument here. In other languages, the
actual function called can depend on the dynamic type of both
arguments, e.g. in CLOS: "(callMe obj arg)", the actual function
called can depend on the type of obj, the type of arg or both
(or neither).

As Alf pointed out, this can get a bit hairy: if both arguments
can have 10 different types, this means 100 different functions.
Which you have to write. And to add a new type, you practically
have to know all of the existing types, in order to add all of
the additional functions.

In practice, in C++, this can be implemented by calling a
virtual function on the first object, and having it call a
virtual function on the second. But with the constraint that
the base class has to know of the existance of all of the
derived types.

--
James Kanze (GABI Software) email:(E-Mail Removed)
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

 
Reply With Quote
 
desktop
Guest
Posts: n/a
 
      05-11-2007
James Kanze wrote:
> On May 11, 12:07 am, desktop <(E-Mail Removed)> wrote:
>> Alf P. Steinbach wrote:
>>> * desktop:
>>>> This page:

>
>>>> http://www.eptacom.net/pubblicazioni/pub_eng/mdisp.html

>
>>>> start with the line: "Virtual functions allow polymorphism on a single
>>>> argument". What does that exactly mean?

>
>>>> I guess it has nothing to do with making multiple arguments in a
>>>> declaration like:

>
>>>> virtual void setId(int a, int b) {id = a+b;}

>
>>> Right. The argument in question is the implicit this-pointer, the
>>> object you're calling the member function on. And what it means is that
>>> what member function implementation to call is selected based on the run
>>> time type of that argument.

>
>> Ok so the argument in question is "obj" in this context:

>
>> obj.callMe()

>
>> where obj is the object that the member function "callMe()" is called upon.

>
> Yes. In C++ syntax. Conceptually, this can be mapped to
> callMe( obj ), with polymorphism always occuring on the first
> object (in C++).
>
> Now consider something like "obj.callMe( arg )". Conceptually,
> this would be "callMe( obj, arg )". In C++, polymorphism only
> works on the first argument here. In other languages, the
> actual function called can depend on the dynamic type of both
> arguments, e.g. in CLOS: "(callMe obj arg)", the actual function
> called can depend on the type of obj, the type of arg or both
> (or neither).
>
> As Alf pointed out, this can get a bit hairy: if both arguments
> can have 10 different types, this means 100 different functions.
> Which you have to write. And to add a new type, you practically
> have to know all of the existing types, in order to add all of
> the additional functions.
>
> In practice, in C++, this can be implemented by calling a
> virtual function on the first object, and having it call a
> virtual function on the second. But with the constraint that
> the base class has to know of the existance of all of the
> derived types.
>




Ok, if we have obj.callMe(arg) the "first" makes sure to find the right
"owner" of obj and uses the virtual functionality to accomplish this.

The "owner object" has as many callMe(arg) functions (specified as
virtual in an abstract base-class) as there are different types of "arg"
objects. In the owner object it could look like this:

callMe(Ball) {}
callMe(Plane) {}
callMe(Bus) {}
callMe(Toy) {}


The "second" call as I understand is just a matter of finding the right
function matching the called argument "arg" through the overloaded
function callMe.

You say that multiple-arg polymorphism deals with two virtual calls, but
are the second not just a regular call to an overloaded function? Or
does it only hold for this example?
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      05-11-2007
On May 11, 3:52 pm, desktop <(E-Mail Removed)> wrote:
> James Kanze wrote:
> > On May 11, 12:07 am, desktop <(E-Mail Removed)> wrote:
> > In practice, in C++, this can be implemented by calling a
> > virtual function on the first object, and having it call a
> > virtual function on the second. But with the constraint that
> > the base class has to know of the existance of all of the
> > derived types.


> Ok, if we have obj.callMe(arg) the "first" makes sure to find the right
> "owner" of obj and uses the virtual functionality to accomplish this.


> The "owner object" has as many callMe(arg) functions (specified as
> virtual in an abstract base-class) as there are different types of "arg"
> objects. In the owner object it could look like this:


> callMe(Ball) {}
> callMe(Plane) {}
> callMe(Bus) {}
> callMe(Toy) {}


> The "second" call as I understand is just a matter of finding the right
> function matching the called argument "arg" through the overloaded
> function callMe.


> You say that multiple-arg polymorphism deals with two virtual calls, but
> are the second not just a regular call to an overloaded function?


No. The first virtual function call resolves the type of the
first object. It ends up in a function of this type, with a
fully typed this. It then calls a virtual function on the
second object, which takes the resolved type as argument. All
of the functions must be present and virtual in the base class,
so we get something like:

class Vehicule
{
public:
virtual void collideWith( Vehicule& other ) = 0 ;

virtual void collideWith( Car& other ) = 0 ;
virtual void collideWith( Bus& other ) = 0 ;
virtual void collideWith( Truck& other ) = 0 ;
// ...
} ;

class Car : public Vehicule
{
public:
virtual void collideWith( Vehicule& other )
{
other.collideWith( *this ) ;
}

virtual void collideWith( Car& other )
{
// Car vs. Car...
}
virtual void collideWith( Bus& other )
{
// Bus vs. Car...
}
virtual void collideWith( Truck& other )
{
// Truck vs. Car...
}
} ;

Vehicule* pCar = new Car ;
Vehicule* pBus = new Bus ;

pCar->collideWith( *pBus ) ;

So what happens here. First, the compiler decides *statically*
which function is to be called (overload resolution), in
Vehicule. Since the argument has the static type Vehicule
(because it is a Vehicule* which is dereferences), the compiler
chooses Vehicule::collideWith( Vehicule& ). Overload resolution
is *always* based on the static type. Since this function is
declared virtual, virtual dispatch occurs, and as a result, we
end up in Car::collideWith( Vehicule& ). But all this does is
call collideWith on the other object. So we start over:
overload resolution in the base class. Except that this time,
the argument is *this, this is a Car* (and not a Vehicule*), so
oeverload resolution chooses Vehicule::collideWith( Car& ) (and
not Vehicule::collideWith( Vehicule& ), as it did the first
time. Again, this function is declared virtual, so virtual
dispatch is applied to "other"; since the actual type is a Bus,
we end up in Bus::collideWith( Car& ) (which I haven't shown).

Basically, each dynamic dispatch works on a single object.
Using this pattern, the first dispatch serves to get us into a
context where the static type is the same as that as the first
object. We then inverse the call, so that the second static
dispatch will call a function based on the type of what was
originally the second argument, with the already resolved type
being used to choose the correct function, by means of overload
resolution.

--
James Kanze (Gabi Software) email: http://www.velocityreviews.com/forums/(E-Mail Removed)
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

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
polymorphism in static member functions? --can it be virtual? newbie C++ 6 04-06-2007 10:22 PM
Polymorphism problem with virtual functions ... Jonas Huckestein C++ 3 02-12-2007 06:01 PM
newbie: allow deny vs deny allow Jeff ASP .Net 2 09-19-2006 02:12 AM
Dynamic polymorphism vs. Static polymorphism Krivenok Dmitry C++ 13 06-01-2006 09:49 AM
Location element in the Web.config file. Allow System Admin whole directory, allow others specific page Ryan Taylor ASP .Net Security 1 09-09-2004 06:52 PM



Advertisments