Advertisement

Testing inheritance

Started by July 18, 2002 04:23 PM
9 comments, last by Arek the Absolute 22 years, 5 months ago
Quick question, say I have these three classes: class CFish{ }; class CHerring : public CFish{ }; class CBillSmith : public CFish{ }; I didn''t give any of them any members, but just assume they''re there for the moment. I had a hard enough time coming up with the class names, so I''m not going to try coming up with variable or function names. Anyway, if I have somewhere in my code: CFish *fish = &some_object; /* some_class is a pointer to either a CHerring or a CBillSmith */ Is there some way I can tell from that fish pointer whether it is in fact a CHerring or a CBillSmith? Or am I going to have to just have a variable within CFish that will keep track of what class it actually is? Just don''t want to waste variables unless necessary, ''cause I''m funny like that. Thanks a bunch! -Arek the Absolute
-Arek the Absolute"The full quartet is pirates, ninjas, zombies, and robots. Create a game which involves all four, and you risk being blinded by the sheer level of coolness involved." - Superpig

  class CFish{	virtual const string getIDname() const { return "Standard Fish"; }	// or =0; if you prefer CFish to be an ADT};class CBillSmith : public CFish{	virtual const string getIDname() const { return "BillSmith"; }};  

No variables needed... and it doesn''t have to be a string, it can be an enum, or a special ID class or whatever...

And don''t worry about the word ADT and the =0 if you don''t know it yet... You can just comment out that... oh no, it was a comment!

/G
---GUI Programming Division Manager at Wildfire Gamesworking on the 0 A.D. project
Advertisement
You can find out the class with 'dynamic_cast', but don't ask me how it works.

@Gee
I see in my crystal ball that your solution won't always work ...

[edited by - Jonus on July 18, 2002 5:32:53 PM]
Well, there's Run-time Type Information (RTTI) which allows you to determine the concrete type of an object at run-time (search Google/Gamedev for 'C++ RTTI').

However, using the inherent power of inheritence is a better option IMO. For exapmle, let's say all fish can swim, but the Herring swims like a normal fish while Bill does a backstroke. Instead of:

  void foo (){  CFish* p_fish = //get your fish  swim(p_fish);}void swim (CFish* p_fish){  switch (getTheTypeOfFish(objectType))  {    case TYPE_HERRING: doFishSwim(p_fish); break;    case TYPE_BILL_SMITH: doBackstroke(p_fish); break;  }}   


give CFish a virtual method called swim() and have it define the default fish swimming, while CBillSmith overrides it to do the backstroke.


  class CFish{  public: virtual void swim ()  {    doFishSwim(this);  }};class CHerring : public CFish{  // inherits CFish::swim};class CBillSmith: public CFish{  // overrides Fish::swim() for custom behavior  public: virtual void swim ()  {    doBackstroke(this);  }};// Use the virtual functionvoid foo (){  CFish* p_fish = //get your fish  p_fish->swim();}   


Now you can add new types of fish to your heart's content without having to modify some massive switch statement.

[edited by - wayfarerx on July 18, 2002 5:43:07 PM]
"There is no reason good should not triumph at least as often as evil. The triumph of anything is a matter of organization. If there are such things as angels, I hope that they're organized along the lines of the mafia." -Kurt Vonnegut
It''s just a non-variable-needed For Beginners solution...

But I can''t see why it wouldn''t always work? I''ve used this method, it worked fine... I can''t think of a as neat solution if it requires dynamic_cast to be used...

But do tell why my solution wouldn''t always work... Maybe it doesn''t, never questioned it before...

/G
---GUI Programming Division Manager at Wildfire Gamesworking on the 0 A.D. project
quote: Original post by Gee
It''s just a non-variable-needed For Beginners solution...

But I can''t see why it wouldn''t always work? I''ve used this method, it worked fine... I can''t think of a as neat solution if it requires dynamic_cast to be used...

But do tell why my solution wouldn''t always work... Maybe it doesn''t, never questioned it before...

/G


I concur. Since all implementations of RTTI I know of use the vtable to determine type, and also use the vtable for the virtual function binding, it seems like the two would be equivalent. What scenario were you thinking of, Jonus?


Don''t listen to me. I''ve had too much coffee.
Advertisement

  class base{   virtual void print(void){cout << "base";}};class x : base{   virtual void print(void){cout << "x";}};class y : base{   virtual void print(void){cout << "y";}};int main(){   base arr[2];   x ax;   y ay;   arr[0] = ax;   arr[1] = ay;   for (int i = 0; i < 2;i++)      arr[i].print();   return 0;}// OUTbasebase    

I hacked it up. so no guarranty.

I am still in investigating this problem, 'cause i need inherance, polymorphism and stuff for my scene graph.


[edited by - Jonus on July 18, 2002 6:27:25 PM]
quote: Original post by Jonus
   arr[0] = ax;   arr[1] = ay;  



Those two lines cast derived types to the base type, discarding subclass-specific information. After you do that, arr[] stores only fish, never herring or that guy. This isn''t a failing of the virtual type() method; merely a way to kill inheritance.


Don''t listen to me. I''ve had too much coffee.
The fun starts here, because with pointers it works well:

        class base{   virtual void print(void){cout << "base";}};class x : base{   virtual void print(void){cout << "x";}};class y : base{   virtual void print(void){cout << "y";}};int main(){   base * arr[2];   x ax;   y ay;   arr[0] = &ax   arr[1] = &ay   for (int i = 0; i < 2;i++)      arr[i]->print();   return 0;}// OUTxy      


[edited by - Jonus on July 18, 2002 6:51:16 PM]
quote: Original post by Jonus
The fun starts here, because with pointers it works well:


Of course; that''s how inheritance works in C++. A derived class may be referenced by a base class pointer. That''s the only real way to use virtual function binding. (Well, okay, references too... but that''s less handy.)

In contrast, when you assign a derived class directly to a base class, you invoke the default, compiler-built typecasting operator, which discards all non-base members.


Don''t listen to me. I''ve had too much coffee.

This topic is closed to new replies.

Advertisement