两个不同类之间的构造函数和析构函数

时间:2013-02-18 19:17:24

标签: c++

所以,我尝试创建两个指向彼此的类(有一个指向另一个类的指针作为私有变量)这里是代码:

class Fruit
{
public:
    Fruit(){
    }
private:
    Plant *thisPlant;
}

class Plant
{
public:
    Plant(){
      thisFruit= new Fruit();
    }
private:
    Fruit *thisFruit;
}

我不确定应该在Fruit构造函数中放入什么。我想我不能把新的Plant()因为它指向一个新工厂,它也会产生一个错误。我希望有这样的东西:植物有一个指向水果的变量。水果有一个指向植物的变量。因为我将在Plant类中使用一些Fruit的公共方法,反之亦然。

关于析构函数,我只想澄清一件事。当我销毁Fruit变量时,如果我没有输入命令“delete thisPlant;”对象植物没有被销毁吗? THX

3 个答案:

答案 0 :(得分:4)

如果您要将new Fruit放在Plant构造函数中,new Plant放置在Fruit构造函数中,那么最终会得到无限递归。创建Plant会创建Fruit会创建Plant会创建Fruit,依此类推。

Plant ---> Fruit ---> Plant ---> Fruit ---> ...

但这显然不是你想要的关系Plant有一个Fruit,但Fruit没有Plant。它肯定希望有一个指向它所属的Plant的指针。

Plant <--> Fruit

为此,您的Fruit构造函数应该使用Plant*类型的单个参数,以允许Plant将指向自身的指针传递给它Fruit具有

class Plant;

class Fruit
{
 public:
  Fruit(Plant* parent){
    parent = parent;
  }
 private:
  Plant* parent;
};

class Plant
{
 public:
  Plant(){
    fruit= new Fruit(this);
  }
 private:
  Fruit* fruit;
};

请注意Plant构造函数将this传递给Fruit。现在PlantFruit之间存在双向关系。 Plant了解其Fruit,而Fruit知道其Plant

现在,请记住每个new必须有delete。这意味着在Plant的析构函数中,您应该delete fruit;。当你销毁Plant时,它的析构函数会破坏它的Fruit。您必须然后使Fruit执行delete parent;,因为其父级已被销毁。 Plant负责销毁Fruit,而不是相反。

答案 1 :(得分:0)

通过'自然'语义层次结构规则Fruit应该使用Plant*指针作为构造函数参数,永远不应该用它的析构函数触及它。

此外,看起来继承自Plant类的具体类应该负责创建Fruit类的实例(使用类似new ConcreteFruit(this)的s.th.)。您可以在Plant基类中提供Destructor实现,该实现将在销毁时销毁此实例。

我认为FruitPlant可以是抽象类,在这里你可以得到像

这样的具体对
class CherryTree : public Plant 
{ 
    // ... 
}

class Cherry : public Fruit 
{ 
    Cherry(CheryTree* plant) : Fruit(plant) {}
    // ... 
}

或者你需要一些使用类属性构建对的机制(例如std::string plantName&lt; =&gt; std::string fruitName)。

答案 2 :(得分:0)

为了摆脱鸡蛋问题,你可以使用模板:

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;

请注意,您需要提供某种控制机制以避免递归(请参阅sftrabbit's回答)。

但请注意,在上面给出的实现中存在循环依赖,因此删除对象非常困难。