Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c++ > #11909 > unrolled thread

Is this bad? (How can this be avoided?)

Started bymike3 <mike4ty4@yahoo.com>
First post2011-11-28 13:44 -0800
Last post2011-11-30 18:26 +0000
Articles 13 — 6 participants

Back to article view | Back to comp.lang.c++


Contents

  Is this bad? (How can this be avoided?) mike3 <mike4ty4@yahoo.com> - 2011-11-28 13:44 -0800
    Re: Is this bad? (How can this be avoided?) Leigh Johnston <leigh@i42.co.uk> - 2011-11-28 22:16 +0000
      Re: Is this bad? (How can this be avoided?) mike3 <mike4ty4@yahoo.com> - 2011-11-28 15:16 -0800
        Re: Is this bad? (How can this be avoided?) Ian Collins <ian-news@hotmail.com> - 2011-11-29 13:04 +1300
          Re: Is this bad? (How can this be avoided?) mike3 <mike4ty4@yahoo.com> - 2011-11-28 17:17 -0800
            Re: Is this bad? (How can this be avoided?) Ian Collins <ian-news@hotmail.com> - 2011-11-29 14:28 +1300
        Re: Is this bad? (How can this be avoided?) "MikeWhy" <boat042-nospam@yahoo.com> - 2011-11-28 19:17 -0600
        Re: Is this bad? (How can this be avoided?) Leigh Johnston <leigh@i42.co.uk> - 2011-11-29 14:12 +0000
    Re: Is this bad? (How can this be avoided?) Goran <goran.pusic@gmail.com> - 2011-11-29 00:06 -0800
    Re: Is this bad? (How can this be avoided?) jgk@panix.com (Joe keane) - 2011-11-30 17:43 +0000
      Re: Is this bad? (How can this be avoided?) "MikeWhy" <boat042-nospam@yahoo.com> - 2011-11-30 12:26 -0600
        Re: Is this bad? (How can this be avoided?) jgk@panix.com (Joe keane) - 2011-11-30 20:36 +0000
      Re: Is this bad? (How can this be avoided?) Leigh Johnston <leigh@i42.co.uk> - 2011-11-30 18:26 +0000

#11909 — Is this bad? (How can this be avoided?)

Frommike3 <mike4ty4@yahoo.com>
Date2011-11-28 13:44 -0800
SubjectIs this bad? (How can this be avoided?)
Message-ID<52997172-c9ca-4e1b-aad0-98fc277268a8@g1g2000pri.googlegroups.com>
Hi.

Is this bad? Suppose you have something like this:

---
class Shape {
      ... blah ...
};

class Rectangle : public Shape {
      ... blah ...
};

class Circle : public Shape {
      ... blah ...
};

... blah ...

class Drawing {
      private:
        ... blah ...
        std::vector<Shape *> shapeList;
        ... blah ...
      public:
        ... blah ...
        void addShape(Shape *s)
        {
             shapeList.push_back(s);
        }
        ... blah ...
        void doSmth(); // uses the objects in shapeList somehow
        ... blah ...
};
---

There could arise a situation like this:

---
void someFunction()
{
     Drawing drawing;

     ... blah ...
     {
         Circle circle(35.0, 55.0, 25.0); // make a circle & (35, 55)
with
                                          // radius 25
         drawing.addShape(&circle);       // add it to the drawing
         // OOPS! circle goes out of scope...!
     }

     ... blah ...

     drawing.doSmth(); // BOOM!

     ... blah ...
}
---

What to do? Now one could, I suppose, change to Circle* circle = new
Circle(35.0, 55.0, 25.0);, but then we need something to take care of
the garbage. Adding a delete() in, say, the destructor for Drawing
might work, but we make some assumptions that may or may not be true,
i.e. one can break it by misusing it, e.g. if one does not use a new
to get the parameter or one forgets that destroying drawing also
destroys circle, etc. Is it a bad idea to rely on the user's
understanding -- to me it doesn't seem so. What should be done?

[toc] | [next] | [standalone]


#11911

FromLeigh Johnston <leigh@i42.co.uk>
Date2011-11-28 22:16 +0000
Message-ID<iP-dnQr9WMmhlUnTnZ2dnUVZ8qmdnZ2d@giganews.com>
In reply to#11909
On 28/11/2011 21:44, mike3 wrote:
> Hi.
>
> Is this bad? Suppose you have something like this:
>
> ---
> class Shape {
>        ... blah ...
> };
>
> class Rectangle : public Shape {
>        ... blah ...
> };
>
> class Circle : public Shape {
>        ... blah ...
> };
>
> ... blah ...
>
> class Drawing {
>        private:
>          ... blah ...
>          std::vector<Shape *>  shapeList;
>          ... blah ...
>        public:
>          ... blah ...
>          void addShape(Shape *s)
>          {
>               shapeList.push_back(s);
>          }
>          ... blah ...
>          void doSmth(); // uses the objects in shapeList somehow
>          ... blah ...
> };
> ---
>
> There could arise a situation like this:
>
> ---
> void someFunction()
> {
>       Drawing drawing;
>
>       ... blah ...
>       {
>           Circle circle(35.0, 55.0, 25.0); // make a circle&  (35, 55)
> with
>                                            // radius 25
>           drawing.addShape(&circle);       // add it to the drawing
>           // OOPS! circle goes out of scope...!
>       }
>
>       ... blah ...
>
>       drawing.doSmth(); // BOOM!
>
>       ... blah ...
> }
> ---
>
> What to do? Now one could, I suppose, change to Circle* circle = new
> Circle(35.0, 55.0, 25.0);, but then we need something to take care of
> the garbage. Adding a delete() in, say, the destructor for Drawing
> might work, but we make some assumptions that may or may not be true,
> i.e. one can break it by misusing it, e.g. if one does not use a new
> to get the parameter or one forgets that destroying drawing also
> destroys circle, etc. Is it a bad idea to rely on the user's
> understanding -- to me it doesn't seem so. What should be done?

Easy: use std::vector<std::tr1::shared_ptr<Shape> > (pre C++11) or 
std::vector<std::unique_ptr<Shape> > (C++11) instead or take a look at 
the Boost "ptr" containers.

/Leigh

[toc] | [prev] | [next] | [standalone]


#11917

Frommike3 <mike4ty4@yahoo.com>
Date2011-11-28 15:16 -0800
Message-ID<d93699f8-e11f-4685-8e72-5053a29e71f4@h37g2000pri.googlegroups.com>
In reply to#11911
On Nov 28, 3:16 pm, Leigh Johnston <le...@i42.co.uk> wrote:
> On 28/11/2011 21:44, mike3 wrote:
>
>
>
> > Hi.
>
> > Is this bad? Suppose you have something like this:
>
> > ---
> > class Shape {
> >        ... blah ...
> > };
>
> > class Rectangle : public Shape {
> >        ... blah ...
> > };
>
> > class Circle : public Shape {
> >        ... blah ...
> > };
>
> > ... blah ...
>
> > class Drawing {
> >        private:
> >          ... blah ...
> >          std::vector<Shape *>  shapeList;
> >          ... blah ...
> >        public:
> >          ... blah ...
> >          void addShape(Shape *s)
> >          {
> >               shapeList.push_back(s);
> >          }
> >          ... blah ...
> >          void doSmth(); // uses the objects in shapeList somehow
> >          ... blah ...
> > };
> > ---
>
> > There could arise a situation like this:
>
> > ---
> > void someFunction()
> > {
> >       Drawing drawing;
>
> >       ... blah ...
> >       {
> >           Circle circle(35.0, 55.0, 25.0); // make a circle&  (35, 55)
> > with
> >                                            // radius 25
> >           drawing.addShape(&circle);       // add it to the drawing
> >           // OOPS! circle goes out of scope...!
> >       }
>
> >       ... blah ...
>
> >       drawing.doSmth(); // BOOM!
>
> >       ... blah ...
> > }
> > ---
>
> > What to do? Now one could, I suppose, change to Circle* circle = new
> > Circle(35.0, 55.0, 25.0);, but then we need something to take care of
> > the garbage. Adding a delete() in, say, the destructor for Drawing
> > might work, but we make some assumptions that may or may not be true,
> > i.e. one can break it by misusing it, e.g. if one does not use a new
> > to get the parameter or one forgets that destroying drawing also
> > destroys circle, etc. Is it a bad idea to rely on the user's
> > understanding -- to me it doesn't seem so. What should be done?
>
> Easy: use std::vector<std::tr1::shared_ptr<Shape> > (pre C++11) or
> std::vector<std::unique_ptr<Shape> > (C++11) instead or take a look at
> the Boost "ptr" containers.
>
> /Leigh

And should the function addShape() be upgraded to use shared_ptr?

And also, though this solves the "garbage collection" issue, it still
seems
the user needs to understand that they must pass an object that's on
the heap,
and that it will be lost when the Drawing object is gone. Is that OK?

[toc] | [prev] | [next] | [standalone]


#11919

FromIan Collins <ian-news@hotmail.com>
Date2011-11-29 13:04 +1300
Message-ID<9jilrvF4d0U26@mid.individual.net>
In reply to#11917
On 11/29/11 12:16 PM, mike3 wrote:
> On Nov 28, 3:16 pm, Leigh Johnston<le...@i42.co.uk>  wrote:
>> On 28/11/2011 21:44, mike3 wrote:
>>
>><snip code>
>>
>>> What to do? Now one could, I suppose, change to Circle* circle = new
>>> Circle(35.0, 55.0, 25.0);, but then we need something to take care of
>>> the garbage. Adding a delete() in, say, the destructor for Drawing
>>> might work, but we make some assumptions that may or may not be true,
>>> i.e. one can break it by misusing it, e.g. if one does not use a new
>>> to get the parameter or one forgets that destroying drawing also
>>> destroys circle, etc. Is it a bad idea to rely on the user's
>>> understanding -- to me it doesn't seem so. What should be done?
>>
>> Easy: use std::vector<std::tr1::shared_ptr<Shape>  >  (pre C++11) or
>> std::vector<std::unique_ptr<Shape>  >  (C++11) instead or take a look at
>> the Boost "ptr" containers.
>
> And should the function addShape() be upgraded to use shared_ptr?
>
> And also, though this solves the "garbage collection" issue, it still
> seems
> the user needs to understand that they must pass an object that's on
> the heap,
> and that it will be lost when the Drawing object is gone. Is that OK?

Most drawing libraries I've used work this way, the container "owns" the 
drawable objects.  The simplest solution is to have the Drawing 
destructor free all of the Shape objects it owns.  So they all assume 
the drawable objects are on the heap.

If you want something more complex, such as the same shape in more than 
one drawing, then something like a shared_ptr is the solution.

-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#11923

Frommike3 <mike4ty4@yahoo.com>
Date2011-11-28 17:17 -0800
Message-ID<b679461b-efc3-4bda-ba5f-a68d2aaaed7c@v31g2000prg.googlegroups.com>
In reply to#11919
On Nov 28, 5:04 pm, Ian Collins <ian-n...@hotmail.com> wrote:
> On 11/29/11 12:16 PM, mike3 wrote:
>
>
>
> > On Nov 28, 3:16 pm, Leigh Johnston<le...@i42.co.uk>  wrote:
> >> On 28/11/2011 21:44, mike3 wrote:
>
> >><snip code>
>
> >>> What to do? Now one could, I suppose, change to Circle* circle = new
> >>> Circle(35.0, 55.0, 25.0);, but then we need something to take care of
> >>> the garbage. Adding a delete() in, say, the destructor for Drawing
> >>> might work, but we make some assumptions that may or may not be true,
> >>> i.e. one can break it by misusing it, e.g. if one does not use a new
> >>> to get the parameter or one forgets that destroying drawing also
> >>> destroys circle, etc. Is it a bad idea to rely on the user's
> >>> understanding -- to me it doesn't seem so. What should be done?
>
> >> Easy: use std::vector<std::tr1::shared_ptr<Shape>  >  (pre C++11) or
> >> std::vector<std::unique_ptr<Shape>  >  (C++11) instead or take a look at
> >> the Boost "ptr" containers.
>
> > And should the function addShape() be upgraded to use shared_ptr?
>
> > And also, though this solves the "garbage collection" issue, it still
> > seems
> > the user needs to understand that they must pass an object that's on
> > the heap,
> > and that it will be lost when the Drawing object is gone. Is that OK?
>
> Most drawing libraries I've used work this way, the container "owns" the
> drawable objects.  The simplest solution is to have the Drawing
> destructor free all of the Shape objects it owns.  So they all assume
> the drawable objects are on the heap.
>
> If you want something more complex, such as the same shape in more than
> one drawing, then something like a shared_ptr is the solution.
>

So then the requirement of the user to have to explicitly heap
allocate
otherwise bad things could happen is okay?

[toc] | [prev] | [next] | [standalone]


#11924

FromIan Collins <ian-news@hotmail.com>
Date2011-11-29 14:28 +1300
Message-ID<9jiqqgF4d0U28@mid.individual.net>
In reply to#11923
On 11/29/11 02:17 PM, mike3 wrote:
> On Nov 28, 5:04 pm, Ian Collins<ian-n...@hotmail.com>  wrote:
>> On 11/29/11 12:16 PM, mike3 wrote:
>>
>>
>>
>>> On Nov 28, 3:16 pm, Leigh Johnston<le...@i42.co.uk>    wrote:
>>>> On 28/11/2011 21:44, mike3 wrote:
>>
>>>> <snip code>
>>
>>>>> What to do? Now one could, I suppose, change to Circle* circle = new
>>>>> Circle(35.0, 55.0, 25.0);, but then we need something to take care of
>>>>> the garbage. Adding a delete() in, say, the destructor for Drawing
>>>>> might work, but we make some assumptions that may or may not be true,
>>>>> i.e. one can break it by misusing it, e.g. if one does not use a new
>>>>> to get the parameter or one forgets that destroying drawing also
>>>>> destroys circle, etc. Is it a bad idea to rely on the user's
>>>>> understanding -- to me it doesn't seem so. What should be done?
>>
>>>> Easy: use std::vector<std::tr1::shared_ptr<Shape>    >    (pre C++11) or
>>>> std::vector<std::unique_ptr<Shape>    >    (C++11) instead or take a look at
>>>> the Boost "ptr" containers.
>>
>>> And should the function addShape() be upgraded to use shared_ptr?
>>
>>> And also, though this solves the "garbage collection" issue, it still
>>> seems
>>> the user needs to understand that they must pass an object that's on
>>> the heap,
>>> and that it will be lost when the Drawing object is gone. Is that OK?
>>
>> Most drawing libraries I've used work this way, the container "owns" the
>> drawable objects.  The simplest solution is to have the Drawing
>> destructor free all of the Shape objects it owns.  So they all assume
>> the drawable objects are on the heap.
>>
>> If you want something more complex, such as the same shape in more than
>> one drawing, then something like a shared_ptr is the solution.
>>
>
> So then the requirement of the user to have to explicitly heap
> allocate
> otherwise bad things could happen is okay?

It's certainly not uncommon.  See the Qt documentation for an example.

-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#11922

From"MikeWhy" <boat042-nospam@yahoo.com>
Date2011-11-28 19:17 -0600
Message-ID<jb1brc$jg0$1@dont-email.me>
In reply to#11917
mike3 wrote:
> On Nov 28, 3:16 pm, Leigh Johnston <le...@i42.co.uk> wrote:
>> On 28/11/2011 21:44, mike3 wrote:
>>
>>
>>
>>> Hi.
>>
>>> Is this bad? Suppose you have something like this:
>>
>>> ---
>>> class Shape {
>>> ... blah ...
>>> };
>>
>>> class Rectangle : public Shape {
>>> ... blah ...
>>> };
>>
>>> class Circle : public Shape {
>>> ... blah ...
>>> };
>>
>>> ... blah ...
>>
>>> class Drawing {
>>> private:
>>> ... blah ...
>>> std::vector<Shape *> shapeList;
>>> ... blah ...
>>> public:
>>> ... blah ...
>>> void addShape(Shape *s)
>>> {
>>> shapeList.push_back(s);
>>> }
>>> ... blah ...
>>> void doSmth(); // uses the objects in shapeList somehow
>>> ... blah ...
>>> };
>>> ---
>>
>>> There could arise a situation like this:
>>
>>> ---
>>> void someFunction()
>>> {
>>> Drawing drawing;
>>
>>> ... blah ...
>>> {
>>> Circle circle(35.0, 55.0, 25.0); // make a circle& (35, 55)
>>> with
>>> // radius 25
>>> drawing.addShape(&circle); // add it to the drawing
>>> // OOPS! circle goes out of scope...!
>>> }
>>
>>> ... blah ...
>>
>>> drawing.doSmth(); // BOOM!
>>
>>> ... blah ...
>>> }
>>> ---
>>
>>> What to do? Now one could, I suppose, change to Circle* circle = new
>>> Circle(35.0, 55.0, 25.0);, but then we need something to take care
>>> of the garbage. Adding a delete() in, say, the destructor for
>>> Drawing might work, but we make some assumptions that may or may
>>> not be true, i.e. one can break it by misusing it, e.g. if one does
>>> not use a new to get the parameter or one forgets that destroying
>>> drawing also destroys circle, etc. Is it a bad idea to rely on the
>>> user's understanding -- to me it doesn't seem so. What should be
>>> done?
>>
>> Easy: use std::vector<std::tr1::shared_ptr<Shape> > (pre C++11) or
>> std::vector<std::unique_ptr<Shape> > (C++11) instead or take a look
>> at the Boost "ptr" containers.
>>
>> /Leigh
>
> And should the function addShape() be upgraded to use shared_ptr?
>
> And also, though this solves the "garbage collection" issue, it still
> seems
> the user needs to understand that they must pass an object that's on
> the heap,
> and that it will be lost when the Drawing object is gone. Is that OK?

After the benefit of many years of occasionally revisiting ye olde taxonomy 
on geometry problem, I offer the following as general advice and specific 
comment for this particular question.

For polymorphic heirarchies, the base class defines how the outside world 
interacts with the concrete sub-types. Its role and content deserve much 
more thought and effort than simply "...blah...", before diving immediately 
into the derived types. Doing so places the proverbial cart before the 
horse, as it were.

Further, almost all "solutions" miss the key abstractions, focusing instead 
on the relatively meaningless distinction between rectangles, circles, and 
pentagons, ad nauseum. The vertex-list, or vertex generation, seems implicit 
in every naive implementation, but I've seen little effort to bring it 
forward as an explicit, exploitable concept.

Last, the more important distinction from my point of view is the difference 
between a spline, and a haphazard shape connected by straight line segments.

On the other hand, if ye olde professor truly did intend for you to focus on 
the trivialities of four-sided versus five-sided regular geometric shapes, 
stick with his program, however much you might feel above this simplistic 
learning. The larger danger is in over-engineering the solution and still 
missing the simplistic mark that was placed before you.

==========================

class Shape2D {
public:
    Shape2D(Vertex2D originXY);
    Shape2D(Vertex2D originXY, Vertex2D scaleXY);
    Shape2D(Vertex2D originXY, Vertex2D scaleXY, Scalar rotation);

    // Shape2D(const Shape2D &); // default copy is appropriate.
    void Draw(Canvas2D &) const;


    // void SetColor(Color);    // as needed
    ...

private:
    virtual DrawTo(Canvas2D &) const = 0;    // abstract

    Vertex2D  origin;
    Vertex2D  scale;
    Scalar    rotationXY;
    VertexGen & vertices;
};

[toc] | [prev] | [next] | [standalone]


#11955

FromLeigh Johnston <leigh@i42.co.uk>
Date2011-11-29 14:12 +0000
Message-ID<XJGdnaL7G434dUnTnZ2dnUVZ8radnZ2d@giganews.com>
In reply to#11917
On 28/11/2011 23:16, mike3 wrote:
> On Nov 28, 3:16 pm, Leigh Johnston<le...@i42.co.uk>  wrote:
>> On 28/11/2011 21:44, mike3 wrote:
>>
>>
>>
>>> Hi.
>>
>>> Is this bad? Suppose you have something like this:
>>
>>> ---
>>> class Shape {
>>>         ... blah ...
>>> };
>>
>>> class Rectangle : public Shape {
>>>         ... blah ...
>>> };
>>
>>> class Circle : public Shape {
>>>         ... blah ...
>>> };
>>
>>> ... blah ...
>>
>>> class Drawing {
>>>         private:
>>>           ... blah ...
>>>           std::vector<Shape *>    shapeList;
>>>           ... blah ...
>>>         public:
>>>           ... blah ...
>>>           void addShape(Shape *s)
>>>           {
>>>                shapeList.push_back(s);
>>>           }
>>>           ... blah ...
>>>           void doSmth(); // uses the objects in shapeList somehow
>>>           ... blah ...
>>> };
>>> ---
>>
>>> There could arise a situation like this:
>>
>>> ---
>>> void someFunction()
>>> {
>>>        Drawing drawing;
>>
>>>        ... blah ...
>>>        {
>>>            Circle circle(35.0, 55.0, 25.0); // make a circle&    (35, 55)
>>> with
>>>                                             // radius 25
>>>            drawing.addShape(&circle);       // add it to the drawing
>>>            // OOPS! circle goes out of scope...!
>>>        }
>>
>>>        ... blah ...
>>
>>>        drawing.doSmth(); // BOOM!
>>
>>>        ... blah ...
>>> }
>>> ---
>>
>>> What to do? Now one could, I suppose, change to Circle* circle = new
>>> Circle(35.0, 55.0, 25.0);, but then we need something to take care of
>>> the garbage. Adding a delete() in, say, the destructor for Drawing
>>> might work, but we make some assumptions that may or may not be true,
>>> i.e. one can break it by misusing it, e.g. if one does not use a new
>>> to get the parameter or one forgets that destroying drawing also
>>> destroys circle, etc. Is it a bad idea to rely on the user's
>>> understanding -- to me it doesn't seem so. What should be done?
>>
>> Easy: use std::vector<std::tr1::shared_ptr<Shape>  >  (pre C++11) or
>> std::vector<std::unique_ptr<Shape>  >  (C++11) instead or take a look at
>> the Boost "ptr" containers.
>>
>> /Leigh
>
> And should the function addShape() be upgraded to use shared_ptr?
>
> And also, though this solves the "garbage collection" issue, it still
> seems
> the user needs to understand that they must pass an object that's on
> the heap,
> and that it will be lost when the Drawing object is gone. Is that OK?

Personally I wouldn't use shared_ptr as the Shape objects are not shared 
but I would do what Ian suggested and have the Drawing destructor delete 
the Shape objects.  I would also use std::auto_ptr in addShape member 
function to make it both explicit that Drawing takes ownership of the 
heap created object and to introduce exception safety:

         void addShape(std::auto_ptr<Shape> s)
         {
              shapeList.push_back(s.get());
              s.release();
         }

HTH.

/Leigh

[toc] | [prev] | [next] | [standalone]


#11936

FromGoran <goran.pusic@gmail.com>
Date2011-11-29 00:06 -0800
Message-ID<6021fa75-d089-4055-8b09-e6fea8ea402e@l19g2000yqc.googlegroups.com>
In reply to#11909
On Nov 28, 10:44 pm, mike3 <mike4...@yahoo.com> wrote:
> Hi.
>
> Is this bad? Suppose you have something like this:
>
> ---
> class Shape {
>       ... blah ...
>
> };
>
> class Rectangle : public Shape {
>       ... blah ...
>
> };
>
> class Circle : public Shape {
>       ... blah ...
>
> };
>
> ... blah ...
>
> class Drawing {
>       private:
>         ... blah ...
>         std::vector<Shape *> shapeList;
>         ... blah ...
>       public:
>         ... blah ...
>         void addShape(Shape *s)
>         {
>              shapeList.push_back(s);
>         }
>         ... blah ...
>         void doSmth(); // uses the objects in shapeList somehow
>         ... blah ...};
>
> ---
>
> There could arise a situation like this:
>
> ---
> void someFunction()
> {
>      Drawing drawing;
>
>      ... blah ...
>      {
>          Circle circle(35.0, 55.0, 25.0); // make a circle & (35, 55)
> with
>                                           // radius 25
>          drawing.addShape(&circle);       // add it to the drawing
>          // OOPS! circle goes out of scope...!
>      }
>
>      ... blah ...
>
>      drawing.doSmth(); // BOOM!
>
>      ... blah ...}
>
> ---
>
> What to do? Now one could, I suppose, change to Circle* circle = new
> Circle(35.0, 55.0, 25.0);, but then we need something to take care of
> the garbage. Adding a delete() in, say, the destructor for Drawing
> might work, but we make some assumptions that may or may not be true,
> i.e. one can break it by misusing it, e.g. if one does not use a new
> to get the parameter or one forgets that destroying drawing also
> destroys circle, etc. Is it a bad idea to rely on the user's
> understanding -- to me it doesn't seem so. What should be done?

To state the obvious... Your question is relatively unrelated to your
example. It's about probably the most important aspect of C++
programming practice: who or what OWNS objects that are in your code.
IIRC, Stroustroup (and standard? dunno) talk about storage classes:

1. static: objects created at startup (before main) and destroyed at
exit (after main)
2. automatic: objects created inside a block (any {} is a block)
3. dynamic: objects created using new

For 1 and 2, owner is language runtime. For 3, owner is the code
itself, or the programmer. So you, the programmer, have to make rules
and obey them to the letter. That includes your users.

There's NO WAY, whatsoever, to avoid that.

For example, Leigh said use shared_ptr. That's a reasonable advice,
but you or your user still MUST obey the rule that shared_ptr owns the
object and must NOT, ever, do e.g. Shape s; shared_ptr<Shape>(&s);. Of
course, with a shared_ptr, or other smart pointers, it's such a common
knowledge that you can only create them with heap objects, which makes
it a good idea to always use smart pointers for heap objects.

So... You need to make a decision and stick to it. If you e.g. decide
to "take ownership" of a Shape in addShape, it's possibly best to make
it "void addShape(auto_ptr<Shape>)" (or unique_ptr) and benefit from
aforementioned common knowledge. Your users are at fault if they don't
use knowledge ;-).

Goran.

[toc] | [prev] | [next] | [standalone]


#11988

Fromjgk@panix.com (Joe keane)
Date2011-11-30 17:43 +0000
Message-ID<jb5pvm$prk$1@reader1.panix.com>
In reply to#11909
In article <52997172-c9ca-4e1b-aad0-98fc277268a8@g1g2000pri.googlegroups.com>,
mike3  <mike4ty4@yahoo.com> wrote:
>class Drawing {
>      private:
>        ... blah ...
>        std::vector<Shape *> shapeList;
>        ... blah ...
>      public:
>        ... blah ...
>        void addShape(Shape *s)
>        {
>             shapeList.push_back(s);
>        }
>        ... blah ...
>        void doSmth(); // uses the objects in shapeList somehow
>        ... blah ...
>};

Maybe you want

    std::vector<Shape> shapeList;

instead?

[toc] | [prev] | [next] | [standalone]


#11989

From"MikeWhy" <boat042-nospam@yahoo.com>
Date2011-11-30 12:26 -0600
Message-ID<jb5sg4$dje$1@dont-email.me>
In reply to#11988
"Joe keane" <jgk@panix.com> wrote in message 
news:jb5pvm$prk$1@reader1.panix.com...
> In article 
> <52997172-c9ca-4e1b-aad0-98fc277268a8@g1g2000pri.googlegroups.com>,
> mike3  <mike4ty4@yahoo.com> wrote:
>>class Drawing {
>>      private:
>>        ... blah ...
>>        std::vector<Shape *> shapeList;
>>        ... blah ...
>>      public:
>>        ... blah ...
>>        void addShape(Shape *s)
>>        {
>>             shapeList.push_back(s);
>>        }
>>        ... blah ...
>>        void doSmth(); // uses the objects in shapeList somehow
>>        ... blah ...
>>};
>
> Maybe you want
>
>    std::vector<Shape> shapeList;
>
> instead?

Direct containment doesn't work for polymorphic heirarchies.

[toc] | [prev] | [next] | [standalone]


#11994

Fromjgk@panix.com (Joe keane)
Date2011-11-30 20:36 +0000
Message-ID<jb6443$efd$1@reader1.panix.com>
In reply to#11989
'engage brain before running mouth'

[toc] | [prev] | [next] | [standalone]


#11990

FromLeigh Johnston <leigh@i42.co.uk>
Date2011-11-30 18:26 +0000
Message-ID<g6ednYZ_34XZ6EvTnZ2dnUVZ7sydnZ2d@giganews.com>
In reply to#11988
On 30/11/2011 17:43, Joe keane wrote:
> In article<52997172-c9ca-4e1b-aad0-98fc277268a8@g1g2000pri.googlegroups.com>,
> mike3<mike4ty4@yahoo.com>  wrote:
>> class Drawing {
>>       private:
>>         ... blah ...
>>         std::vector<Shape *>  shapeList;
>>         ... blah ...
>>       public:
>>         ... blah ...
>>         void addShape(Shape *s)
>>         {
>>              shapeList.push_back(s);
>>         }
>>         ... blah ...
>>         void doSmth(); // uses the objects in shapeList somehow
>>         ... blah ...
>> };
>
> Maybe you want
>
>      std::vector<Shape>  shapeList;
>
> instead?

No; 'Shape' is a base class.  Read about "slicing".

/Leigh

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c++


csiph-web