1

だから、私はお互いを指す2つのクラスを作成しようとします(プライベート変数として他のクラスへのポインタを持っています)ここにコードがあります:

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

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

Fruit コンストラクターに何を入れればよいかわかりません。new Plant() は新しいプラントを指し、エラーも発生するため、配置できないと思います。私は次のようなものを持ちたいと思っています: Plant には Fruit を指す変数があります。Fruit には Plant を指す変数があります。Plant クラスで Fruit のパブリック メソッドを使用するため、逆も同様です。

デストラクタに関して、1 つだけ明確にしたいことがあります。Fruit 変数を破棄するとき、コマンド「delete thisPlant;」を入力しないと、オブジェクトプラントは破壊されませんよね?どうも

4

3 に答える 3

4

コンストラクターとコンストラクターを配置new Fruitすると、無限再帰になります。を作成すると、を作成し、を作成し、を作成します。Plantnew PlantFruitPlantFruitPlantFruit

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

しかし、これは明らかにあなたが望む関係ではありません。APlantにはがありますFruitが、それFruitは違いはありませんPlant。それは確かにそれが含まれているものへのポインタを持ちたいと思っていますPlant

Plant <--> Fruit

これを行うには、Fruitコンストラクターが型の単一のパラメーターを取り、それ自体へのポインターをコンストラクターが持つパラメーターに渡すPlant*ことができるようにする必要があります。PlantFruit

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。現在、との間には双方向の関係がPlantありFruitます。はそのPlantことを知っておりFruit、そのことをFruit知っていますPlant

newここで、すべてにが必要であることを忘れないでくださいdelete。つまり、のデストラクタではPlant、を実行する必要がありますdelete fruit;。を破棄するPlantと、そのデストラクタはそのを破棄しFruitます。その親はすでに破壊されているので、あなたはそれからやるべきではありません。はその破壊に責任があり、その逆ではありません。Fruitdelete parent;PlantFruit

于 2013-02-18T19:27:22.797 に答える
0

「自然な」セマンティック階層ルールを使用して、クラスはコンストラクター引数としてポインターをFruit取得する必要があり、デストラクタでポインターに触れないようにする必要があります。Plant*

さらに、クラスから継承する具象クラスPlantは、クラスのインスタンスを作成する責任があるように見えますFruit(s.th. likeを使用new ConcreteFruit(this))。Plant破棄時にこのインスタンスを破棄するDestructor実装を基本クラスに提供できます。

私は、次のような具体的なペアを導出する抽象クラスのいずれかである可能性があるFruitと思いますPlant

class CherryTree : public Plant 
{ 
    // ... 
}

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

または、クラス属性を使用してペアを構築するメカニズムが必要になります(例:std::string plantName<=> std::string fruitName)。

于 2013-02-18T19:27:46.697 に答える
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の回答を参照)。

ただし、上記の実装では循環依存があるため、オブジェクトを削除するのは非常に難しいことに注意してください。

于 2013-02-18T19:33:39.157 に答える