Archived

This topic is now archived and is closed to further replies.

Arek the Absolute

Testing inheritance

Recommended Posts

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

Share this post


Link to post
Share on other sites

  
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

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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 function

void 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]

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

  
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;
}

// OUT

base
base

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]

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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;
}

// OUT

x
y


[edited by - Jonus on July 18, 2002 6:51:16 PM]

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites