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.