Click to See Complete Forum and Search --> : Polymorphism? We don't need no stinkin' polymorphism


ThermoSight
July 2nd, 2006, 02:48 PM
Perhaps you can help me understand how polymorphism works ....

I have a test case presented below which, to me, exhibits not polymorphism, but just plain-old "hiding". First, the class declarations ...



#pragma once


namespace Junk
{
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;


// *******************
__gc class base {

public:

base () {};


// Note this ** isn't ** declared 'virtual' - doesn't make any difference
String *ToString(void) {return S"base class here.\r\n";};

};// end class 'base' declaration.


//********************
__gc class derived1 : public base {

public:

derived1() {};

String *ToString(void) {return S"derived1 class here.\r\n";};

};// end class 'derived1' declaration.

//********************
__gc class derived2 : public base {

public:

derived2() {};

String *ToString(void) {return S"derived2 class here.\r\n";};

};// end class 'derived2' declaration.

} // end this segment namespace 'Junk'





Now the code that creates and invokes the classes.....


void Form1::Quickie(void) {

base *pBase = new base();
derived1 *pderived1 = new derived1();
derived2 *pderived2 = new derived2();

MessageBox::Show(String::Concat(pBase->ToString(),
pderived1->ToString(),
pderived2->ToString()));


pBase = reinterpret_cast <base *> (pderived1);

MessageBox::Show(String::Concat(pBase->ToString(),
pderived1->ToString(),
pderived2->ToString()));

} // end function 'Quickie'




Now, the way I thought this should work is that

(a) the word 'virtual' would be required in the base class, or the derived classes would encounter a compilation error. Actually, the word 'virtual' is a don't-care item. It's presence or absence doesn't make any difference that I can see. It compiles either way, and it works the same either way.

(b) when the 'ToString' function was invoked using a derived-class pointer, the function associated with the derived-class would execute, BUT when the 'ToString' function was invoked using a base-class pointer set to the derived-class (see reinterpet_cast statement), the BASE-CLASS function would be invoked. Actually, it doesn't matter which pointer is used .... the derived-class function is invoked.

So, this isn't polymorphism in my book; this is just plain old "hiding" of the base-class function. Where's the fun in that?

yeah, I can kinda get around this with the use of __super::ToString(), but I shouldn't hafta do that. I woulda thought C++'d be more elegant than that. What am I missing here?

Thanks,

bill

cilu
July 2nd, 2006, 04:02 PM
the word 'virtual' would be required in the base class, or the derived classes would encounter a compilation error. Actually, the word 'virtual' is a don't-care item. It's presence or absence doesn't make any difference that I can see. It compiles either way, and it works the same either way.
Nope, you are not correctly understanding what's going on here. base is not actually the base class. It is a reference type, so it is actually derived from Object, which is the base class for any reference type from the .NET framework. One of the methods of Object is

virtual String* ToString ();

Which means ToString is already a virtual method. So in base (as well as derived1 and derived2) you're not doing anything else than overriding it. Notice that the keyword virtual is not required in a derived class (and remember base is a derived class here).

when the 'ToString' function was invoked using a derived-class pointer, the function associated with the derived-class would execute, BUT when the 'ToString' function was invoked using a base-class pointer set to the derived-class (see reinterpet_cast statement), the BASE-CLASS function would be invoked. Actually, it doesn't matter which pointer is used .... the derived-class function is invoked.
And that my friend is called POLYMORPHISM. ;)

Please read these two FAQs (http://www.codeguru.com/forum/showthread.php?t=351122#cpp_polymorphism) about polymorphism.

And please be more careful with the language.

ThermoSight
July 2nd, 2006, 04:24 PM
"base is not actually the base class. It is a reference type, so it is actually derived from Object, which is the base class for any reference type from the .NET framework. "



VERY good point, Cilu, and one I'd obviously overlooked. The Object is the real base class. That explains why the keyword 'virtual' isn't needed in my example.

I got the part about the 'ToString' performing differently based on which derived class is referenced (pderived1->ToString() returns a string different from pderived2->ToString()), but in my book there's nuthin' special about that .... that's just too similar to 'enclosing scope' for me to get excited about that.

Still, your statement above was worth its weight in gold. It answered the question I had. I only THOUGHT my class was the base class ... in fact, it was the underlying Object that was the real base class.

Thanks for the input, Cilu. it helped a lot.

Best wishes,

bill

cilu
July 3rd, 2006, 04:53 AM
You're welcomed. But I really suggest that you read those two FAQs that I pointed you to.