From: dailos on
Hi all,
I am struggling with a design problem. It showed up because of some
architectures constraints.
I have a group of classes which derive from an abstract one.
I have a vector with pointers to the generic abstract class (neither
vector of references nor vector of classes are allowed since it's
abstract).
A member function that loads objects into the vector, lets say from
file, has to do it creating object with new operator since it couldn't
be done by references to objects created locally.
A public functions lets the user to add single objects too but it
could use new or reference as an argument.
The problem is when I need to call the destructor, and erase all of
the objects created within the vector.
I thought of using delete operator for each element in the vector, but
what if some other elements has been added from a reference. delete
&something ## failure.

I guess there is no way to distinguish between object address created
with new and created with a reference.
How a to write a proper destructor then??

Here it is a very easy program that shows the situation.
Thanks!!

#include <iostream>
#include <vector>

using namespace std;

class Fruit
{
public:
virtual string name() = 0;
};

class Orange : public Fruit
{
public:
virtual string name(){return string("Orange");};
};

class Watermelon : public Fruit
{
public:
virtual string name(){return string("Watermelon");};
};

class Apple : public Fruit
{
public:
virtual string name(){return string("Apple");};
};

class Basket
{
public:
void loadFruits();
void addFruit(Fruit* pFruit);
void showFruits();
private:
vector<Fruit*> fruitList;
};

void Basket::loadFruits()
{//adds three fruits
addFruit(new Watermelon());
addFruit(new Orange());
addFruit(new Apple());
}

void Basket::addFruit(Fruit* pFruit)
{
fruitList.push_back(pFruit);
}

void Basket::showFruits()
{
for(unsigned int i=0;i<fruitList.size();++i)
{
cout << fruitList[i]->name() << endl;
}
}

int main()
{
Basket myBasket;
myBasket.loadFruits();
Orange theOrange;
myBasket.addFruit(&theOrange);
myBasket.showFruits();
return 0;
}

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Helge Kruse on

"dailos" <dailos.guerra.r(a)gmail.com> wrote in message news:9887de25-e04b-411b-9347-df6419a7caea(a)d37g2000yqm.googlegroups.com...
> Hi all,
> I am struggling with a design problem. It showed up because of some
> architectures constraints.
> I have a group of classes which derive from an abstract one.
> I have a vector with pointers to the generic abstract class (neither
> vector of references nor vector of classes are allowed since it's
> abstract).
> A member function that loads objects into the vector, lets say from
> file, has to do it creating object with new operator since it couldn't
> be done by references to objects created locally.
> A public functions lets the user to add single objects too but it
> could use new or reference as an argument.
> The problem is when I need to call the destructor, and erase all of
> the objects created within the vector.
> I thought of using delete operator for each element in the vector, but
> what if some other elements has been added from a reference. delete
> &something ## failure.
>
> I guess there is no way to distinguish between object address created
> with new and created with a reference.
> How a to write a proper destructor then??

There are two points that you must consider. First you must distinguish
between object on the heap and objects that are global variables or on the
stack (local variables).
What you have created with new resides on the heap and must be deleted.
Objects on the stack are deleted when the scope is left. Objects in global
variables are deletet on program termination. So you cannot add theOrange'
address to the basket. You could do it, if you somehow indicate that it is
an heap object or not. You could add an flag that could be read during
basket destruction.

<dirty hack>
That's dirty, but you can identify stack, heap and global objects by their
address. But that is not portable between compilers and/or operating system
and o/s versions. So you should not use it.
</dirty hack>

Further you could add a pointer to an object, that is already in the basket.
This case has not been shown in your sample code. If you cannot avoid this,
you need something like a reference counting. Simple to implement, ugly to
use.

BTW: You wrote about reference and I assume you meen adding the same object
to the basket again. C++ references are not an additional pointer to the
same object, but a language construct.

Regards,
Helge


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]