Reputation: 145
So, I try to create two class that pointing to each other (has a pointer to the other class as private variable) here is the code:
class Fruit
{
public:
Fruit(){
}
private:
Plant *thisPlant;
}
class Plant
{
public:
Plant(){
thisFruit= new Fruit();
}
private:
Fruit *thisFruit;
}
I am not sure what should I put in the Fruit constructor. I think I can't put new Plant() because it will pointing to a new plant, and it also will create an error. I want to have something like this: Plant has a variable pointing to Fruit. And the Fruit has a variable pointing to the Plant. Because I will use some Fruit's public method in Plant class, vice versa.
Regarding the destructor, I just want to clarify one thing. when I destroy the Fruit variable, if I do not put command "delete thisPlant;" the object Plant isn't destroyed right? thx
Upvotes: 1
Views: 308
Reputation: 110648
If you were to put new Fruit
in the Plant
constructor and new Plant
in the Fruit
constructor, you'd end up with infinite recursion. Creating a Plant
would create a Fruit
would create a Plant
would create a Fruit
, and so on.
Plant ---> Fruit ---> Plant ---> Fruit ---> ...
But this clearly isn't the relationship you want. A Plant
has a Fruit
, but that Fruit
doesn't have a different Plant
. It surely wants to have a pointer to the Plant
that it is a part of.
Plant <--> Fruit
To do this, your Fruit
constructor should take a single parameter of type Plant*
, to allow the Plant
to pass a pointer to itself to the Fruit
that it has.
class Plant;
class Fruit
{
public:
Fruit(Plant* parent){
parent = parent;
}
private:
Plant* parent;
};
class Plant
{
public:
Plant(){
fruit= new Fruit(this);
}
private:
Fruit* fruit;
};
Notice that the Plant
constructor passes this
to its Fruit
. Now there is a two way relationship between the Plant
and Fruit
. The Plant
knows about its Fruit
and the Fruit
knows about its Plant
.
Now, remember that every new
must have a delete
. That means that in the destructor for Plant
, you should do delete fruit;
. When you destroy a Plant
, its destructor will destroying its Fruit
. You must not then make the Fruit
do delete parent;
because its parent is already being destroyed. The Plant
is responsible for destroying its Fruit
, not the other way around.
Upvotes: 4
Reputation: 1
By means of the 'natural' semantic hierarchy rules class Fruit
should take a Plant*
pointer as constructor argument, and never should touch it with it's destructor.
Further it looks like concrete classes inheriting from Plant
class should be responsible to create an instance of the Fruit
class (using s.th. like new ConcreteFruit(this)
). You can provide a Destructor implementation in the Plant
base class that will destroy this instance on destruction.
I think Fruit
and Plant
could be either abstract classes, where you'll derive concrete pairs like
class CherryTree : public Plant
{
// ...
}
class Cherry : public Fruit
{
Cherry(CheryTree* plant) : Fruit(plant) {}
// ...
}
or you'll need some mechanism build the pairs using class attributes (e.g. std::string plantName
<=> std::string fruitName
).
Upvotes: 0
Reputation: 105876
In order to get rid of the hen-egg problem you can use templates:
template <class PlantType>
class Fruit_impl
{
public:
Fruit_impl(PlantType * parent = 0){
if(parent == 0)
parent = new PlantType(this);
thisPlant = parent;
}
private:
PlantType *thisPlant;
};
class Plant
{
public:
typedef Fruit_impl<Plant> fruit_type;
Plant(fruit_type * parent = 0){
if(parent == 0)
parent = new Fruit<Plant>(this);
thisFruit = parent;
}
private:
fruit_type * thisFruit;
};
typedef Fruit_impl<Plant> Fruit;
Note that you need to give some kind of control mechanism in order to avoid recursion (see sftrabbit's answer).
However, note that in the implementation given above there's a circular dependency, thus it is quite difficult to get delete the objects.
Upvotes: 0