Newsgroups: comp.lang.c++ Path: utzoo!utgpu!cunews!bnrgate!scrumpy!bnrmtl@bnr.ca!pat From: pat@bnrmtl.bnr.ca (Patrick Smith) Subject: Re: About Lists and things... Message-ID: <1991Jun27.175256.3224@scrumpy@.bnr.ca> Sender: news@scrumpy@.bnr.ca (USENET NEWS KJ) Reply-To: bnrmtl!pat@larry.mcrcim.mcgill.edu Organization: Bell Northern Research, Montreal, Canada. References: <2865E7A8.179A@tct.com> <19131@prometheus.megatest.UUCP> <28692A4A.59B7@tct.com> <1991Jun27.095856.2@minerva.inesc.pt> Date: Thu, 27 Jun 91 17:52:56 GMT In article <1991Jun27.095856.2@minerva.inesc.pt>, fmhv@minerva.inesc.pt (Fernando Manuel Vasconcelos) writes: |> In article <28692A4A.59B7@tct.com> chip@tct.com (Chip Salzenberg) writes: |> |> >If you put a Circle into a ShapeList, you lose the Circle's |> >compile-time type, because ShapeList.first() returns |Shape*|. |> >Suppose that you decide to call a Circle-specific function on a Circle |> >stored in a ShapeList. Some would cast the |Shape*| to a |Circle*| |> >and carry on. My coding practice would require you to replace the |> >ShapeList with a CircleList. |> > |> >Of course, that change may not be practical, perhaps because there are |> >other non-Circle objects in the ShapeList. If so, congratulations! |> >You have just discovered that the function in question is actually a |> >Shape function in disguise. You should therefore add it to the Shape |> >interface, presumably as a new virtual function. |> > |> >Clearer now? |> |> I may be missing the point, however consider two objections to your proposal: |> |> 1. A pratical one: You may not be able to change shape.h because it belongs |> to a library which you have only in binary ( of course you have the .h's but |> you can't change them ... ) |> |> 2. A conceptual one: That means the interface of a base class depends on the |> interface of the derived classes. Using your example it is normal that a |> circle should know to answer it's radius. If I keep all my graphical |> objects in a list of shapes* , I'll have to add a getRadius message to |> the Shape class, only because a circle knows what that means ... But a GENERAL |> shape doesn't . I tend to agree with Chip here. But that doesn't mean that I would add a getRadius() method to the Shape class. If getRadius() only makes sense for Circles, then the only way you can use it on an arbitrary Shape is something like this: if ( /* *this is a Circle */ ) // do something with this->getRadius() else // do something else with *this // may be several cases - Squares, Triangles, Blobs, etc. Even if you define getRadius() for any Shape, if it only makes sense for Circles, you're going to get code like the above. The style I prefer is to replace the entire if block with a single call to a virtual function: this->doSomething(); Presumably, "do something" makes sense for every Shape, since you're doing it for an arbitrary Shape you got from a ShapeList. And then you can add appropriate member functions for each type of Shape: Circle::doSomething() { /* uses this->getRadius() */ } Square::doSomething() { /* uses this->sideLength() */ } etc. If you can't change the definition of Shape (or don't want to), you can put another class of your own in between Shape and the specific classes: class MyShape : public Shape { /*...*/ }; class Circle : public MyShape { /*...*/ }; class Square : public MyShape { /*...*/ }; Now you can make doSomething() a method of MyShape. -- Patrick Smith Bell-Northern Research, Montreal, Canada (514) 765-7914 bnrmtl!pat@larry.mcrcim.mcgill.edu patrick@bnr.ca ... Any resemblance between the above views and those of my employer, my terminal, or the view out my window are purely coincidental.