Polymorphism

  • Thread starter Richard Tappenden
  • Start date
R

Richard Tappenden

Hi Armin,

What can I say! I had a good think about this last night (sad, I should have
been drinking or something), and I realised that everything you said about
Abstract classes makes perfect sense.

So, I'll have to look at another way of doing it :D

Thanks again for your help,

Richard
 
A

Armin Zingler

Richard Tappenden said:
Hi Armin,

What can I say! I had a good think about this last night (sad, I
should have been drinking or something), and I realised that
everything you said about Abstract classes makes perfect sense.

So, I'll have to look at another way of doing it :D

Thanks again for your help,

Huh? I'm still trying to understand Tom Shelton's posting, and you are
saying that I was right? :))))
 
R

Richard Tappenden

Hi Armin -

The confusion is with the abstract bit. What I was asking for is essentialy
what VB does with the Overloads stuff.

In C++, you simply do this

Class CBase
{
virtual void DoSomething( CBaseObj obj );
}

void
CBase::DoSomething(CBaseObj obj)
{
// Do Something
}

Class CDerived
{
virtual void DoSomething( CDerivedObj obj );
}

void
CDerived::DoSomething(CDerivedObj obj)
{
// Do something different
}

But of course, if the base method had been abstract it wouldn't make sense.
I was just being a little blind :)

I think Tom & Jay were both explaining how I can do the above, or possibly
that I could do something similar(ish) with abstract method

i.e. I could do this

Class CBase
{
virtual CBaseObj GetObj() = 0;
}

Class CDerived
{
virtual CBaseObj GetObj();
}

CBaseObj
CDerived::GetObj()
{
CDerivedObj derivedObj;
return derivedObj;
}

Sorry for all the confusion!

Richard
 
J

Jay B. Harlow [MVP - Outlook]

Richard,
Yes Tom & I were describing Covariant parameter types, along with some
alternative methods that you can use in .NET instead, which Armin also
described.
But of course, if the base method had been abstract it wouldn't make sense.
I was just being a little blind :)
In C++, if the method is abstract, you can still have covariant parameters.
Class CBase
virtual void DoSomething( CBaseObj obj ) = 0;

Class CDerived
virtual void DoSomething( CDerivedObj obj );

Only CDerived::DoSomething needs an implementation to compile. (verified
with unmanaged code, not tested with managed code).

In .NET you cannot have covariant parameters whether they are abstract or
not.
Class CBase
{
virtual CBaseObj GetObj() = 0;
}
Your template method is a fair alternative.

Hope this helps
Jay
 
R

Richard Tappenden

Hi Jay,

I looked into the C++ thing, it does compile, but I dont think you'll be
able to create an instance of the derived object.

This is what threw me off the scent before, because VB.NET would not
compile - but in C++ the derived class would still be considered abstract,
so it isn't a compilation error at that point - only when you try to
instantiate it.
 
J

Jay B. Harlow [MVP - Outlook]

Richard,
Hmm...

My mistake, C++ only supports Covariant return types, not covariant
parameters.

http://msdn.microsoft.com/msdnmag/issues/02/02/ModernC/default.aspx

I wonder if Whidbey C++ supports Covariant parameters? Or I just remember
that the C++ spec supports them. Either way Visual C++ does not...

Sample of Covariant return type:

class CBase
{
virtual CBaseObj* DoSomething() = 0;
}

class CDerived : public CBase
{
virtual CDerivedObj* DoSomething();
}

With Visual C++ 7.1 you can compile & create a CDerived object. (helps if I
verify you can create the object ;-))

In an earlier post Armin stated something, that I think is partially as to
why Covariant parameters won't work, or at least don't work the way you
would expect...

My mistake for thinking Visual C++ supported Covariant parameters...

Of course with overloading you can get the effect of covariant parameters.

Jay
 
R

Richard Tappenden

Hi Jay,

Thats exactly where I went wrong - I just checked that it compiled :)

I've redesigned the solution now - the base class has an implementation, and
throws an error if it is called. Its not quite a nice as it would have been
(because being abstract it would have forced an implementation higher up),
but at least if it throws an error, we'll soon realise that the specialised
version hasn't been written.

Another question though -

I have something like this:

CBase
Function DoSomething( ByRef myObj CBaseObj)
'Blah
End Function

CDerived
Function DoSomethingElse(ByRef myObj As CDerivedObj)
MyBase.DoSomething(myObj)
End Function

This doesn't work - it asks me to cast the CDerivedObj to a CBaseObj.
However, if I change DoSomethingElse to be passed in ByVal, it works ok. It
isn't really a problem, but I am just curious as to the reason...

Thanks again for your help!

Richard
 
J

Jay B. Harlow [MVP - Outlook]

Richard,
Function DoSomething( ByRef myObj CBaseObj)
I believe you are confusing ByVal & ByRef Parameters with Value & Reference
Types.

My standard FAQ on ByVal & ByRef verses Value Types & Reference Types
(Knowing C++ I'm sure you know allot of this, except maybe not in the
context of VB.NET):

ByVal & ByRef Parameters are independent of Reference & Value Types. All
parameters by default are passed ByVal, you should only pass a parameter
ByRef when you have to, which is when you need to modify the callers
variable.

Less memory use & better performance should not be a factor in choosing
ByVal & ByRef. The only time to consider ByRef for less memory & performance
is when passing large structures (structures as in defined with the
Structure keyword), however structures should never be large!

Structure Usage Guidelines.
http://msdn.microsoft.com/library/d...genref/html/cpconvaluetypeusageguidelines.asp

A Reference Type is an object that exists on the heap. If I have a variable
that is a reference type and assign the variable to another variable. Both
variables will be pointing to the same object on the heap.

Dim x As Person
x = New Person()
Dim y As Person
y = x

Both x & y are the exact same Person object on the heap.

A Value Type does not live on the Heap. If I have a value type variable and
I assign it to another variable, a copy of the value is made.

Dim x As Integer
x = 100
Dim y As Integer
y = x

Although both x & y have the value 100, they are physically different values
as a copy was made.

Now when you pass a variable to a ByVal parameter a copy of the variable is
made. So for a Reference Type a copy of the reference is made, which means
there is still only one object on the heap & two references to that object.
For a Value Type a copy of the value is made.

When you pass a variable to a ByRef parameter a reference to that variable
is made. So for a Reference Type you have a reference to a reference to the
object, for a Value Type you have a reference to the value.

Remember ByVal & ByRef are how parameters are passed. Reference & Value
Types are how quantities are stored.

Hope this helps
Jay
 
R

Richard Tappenden

Hi Jay,

Thanks for the info - I did realise that you passed ByRef so you can change
the values, and only recently found out that they are no more efficient
(where as in C++ it is 'heaps' (sorry, couldn't resist) more efficient).
Obviously if you didnt want the value changed, you'd pass it in as a const
ref.

I'm still not 100% sure why I cannot pass a derived object through as a base
object if it is ByRef, but I guess there must be a good reason for it :)

Cheers,

Richard
 
J

Jay B. Harlow [MVP - Outlook]

Richard,
I'm still not 100% sure why I cannot pass a derived object through as a base
object if it is ByRef, but I guess there must be a good reason for it :)
ByRef by definition implies that the called routine can modify the calling
routines variable. Think will modify calling routine variable! The called
routine can assign any object that derives from its parameter type to the
ByRef parameter.

Option Strict On, prevents implicit conversions, you need to explicitly give
the conversion...

Consider the following:
I have something like this:

CBase
Function DoSomething( ByRef myObj CBaseObj) myObj = New COtherObj ()
End Function

CDerived : inherits CBase
Function DoSomethingElse(ByRef myObj As CDerivedObj)
MyBase.DoSomething(myObj)
End Function

COtherObj : inherits CBaseObj


Dim derived As New CDerived
derived.DoSomethingElse

Notice that CBase.DoSomething can 'return' (via the ByRef parameter) a
COtherObj, as COtherObj inherits from CBaseObj. However CDerived cannot put
a COtherObj into a CDerivedObj variable as COtherObj does not inherit from
CDerivedObj.
Obviously if you didnt want the value changed, you'd pass it in as a const
ref.
As you know "const-ness" is a C++ feature that is not found in .NET, you
could always use MS wish to send a request for it ;-)

Hope this helps
Jay
 
R

Richard Tappenden

Hi Jay,

That kinda makes sense I suppose - although if you do get it as the base
version, I dont see why you shouldn't be able to change any base properties
of the parameter.

I might do the wish thing, but MS might end up getting fed up with me :D

Richard.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top