1

C++ でコンポジション サンプル アプリを作成するのを手伝ってくれませんか?

私はそのような階層が必要です: クラス AppleCake は基本クラス Cake から継承し、4 つのケーキを持つクラス CakePacket があります。コードの一部を書いていますが、問題は CakePacket に 4 つの Cake オブジェクトを追加する方法がわからないことです。私はC++の初心者なので、ばかげたエラーがある場合は申し訳ありません。

#include <iostream>
using namespace std;

class Cake {

protected:
  int cost;
public:
  void setCostr(int a) { cost = a; }
  int getCost() { return cost; }
  Cake(int x) { cost = x;  }
  ~Cake() {  }
};


class AppleCake : public Cake {
  int diameter;
public:
  int getDiameter() { return diameter; }

  AppleCake(int x, int y): Cake(x)
    { diameter = y; }

  ~AppleCake() {  }
};


class CakePacket 
{
private:
    Cake *cArr;

    CakePacket() { }

public:
    CakePacket(Cake *x)  //there have to be 4 Cake objects in CakePacket
    : cArr(new Cake[4]) {};
};

最後の質問は、CakePacket のオブジェクトを作成する方法です。

後でもう 1 つコンポジションを作成する必要があります。一部のクラスには 1 つの CakePacket が含まれます。しかし、1 つの CakePacket オブジェクトを他のクラスに追加しても問題ないことを願っています。

すべての答えをありがとう!

4

4 に答える 4

7

最後の 1 時間は誰も正解できなかったので... 実際には @taylorc93 が一番近くにいましたが、それでも彼はなんとかミスを犯しました。

では、質問に戻ります。CakePacket は Cakes を保存するはずですよね?Cakeは基本クラスですが、仮想メソッドはありません。このシナリオではポインターを使用する必要はまったくありません。必要なのは、コンテナーを使用することだけです。どちらを選択するかは、CakePacket の使用目的によって異なります。一般的な方法で書きましょう。

class CakePacket {
    // this can be whatever you might need; a list, set, unordered_set...
    // vector is a reasonable default
    vector<Cake> cakes;

public:
    // We'll also need a way to add them:
    void addCake(Cake cake) {
        // I'm moving the parameter to avoid copying
        // refer to "move semantics" to understand it deeper
        cakes.push_back(std::move(cake));
    }
};

出来上がり!CakePacket を作成する方法を尋ねましたが、それは非常に簡単です。

CakePacket cp;

cp.addCake(Cake(1));
cp.addCake(Cake(2));
cp.addCake(Cake(3));

もちろん、これらを のコンストラクターに移動することはできますCakePacketが...

CakePacket cp { Cake(1), Cake(2), Cake(3), Cake(4) };

配列のようなリストから作成できるようにしたい場合は、追加のコンストラクター take を提供する必要がありますがinitializer_list<Cake>、それは演習として残します。(ヒント:ループは必要ありませんfor)。

CakePacket は本当に必要ですか?

これは学習上の質問なので、うるさくするつもりはありませんが、少なくとも現在の状態では、CakePacket が実際には何もしないという事実を指摘したいと思います。stdまったく新しい型でラップするよりも、単純にコンテナーを使用する方が簡単な場合があります。これにより、不要なクラスでコードが汚染されるのを回避でき、コンテナを操作するために標準ライブラリが提供する機能の多さに驚かれることでしょう。

警告

その中に AppleCake を保存しようとすると、diameterスライスれます。つまり、共通部分だけが保存されます。その場合、基本クラスへのポインターを格納するか ( または を使用)、または のようなものを使用する必要がboost::ptr_vector<Cake>ありstd::vector<std::unique_ptr<Cake>>ますBoost.Variant

ここで絶対にやりたくないこと

...生のポインタを格納しています。CakePacket dtor に追加された各 Cake を破棄する必要がありますが、これはエラーが発生しやすく、単純に不要です。

C スタイルの配列を使用することも、固定サイズに制約されるため、かなり悪いです。

于 2013-07-08T14:19:26.770 に答える
-1

クラスAのオブジェクトを作成し、

1) スタック内で、
A a

2)ヒープで、
A* pa = new A

などのコンストラクターにパラメーターがある場合はA(int x, int y)、パラメーターを追加し、

A a(1, 2)また A* pa = new A(1, 2)

スタック内のオブジェクトは、定義されたスコープの外に出ると自動的に削除されます。ただし、ヒープ内のオブジェクトは手動で削除する必要があります。

delete pa.

したがって、ケーキの 4 つのオブジェクトを作成するには、オブジェクトにパラメーターを渡す必要があります。たとえば、

    std::vector<Cake*> vec;
    for (int i = 0; i < 4; ++i) {
        vec[i] = new Cake(i);
    }
于 2013-07-08T12:58:30.243 に答える
-1

オブジェクトを CakePacket クラスに追加するには、それを変更する必要があります:

class CakePacket 
{
private:
    Cake *cArr[4];

public:
    CakePacket()  //there have to be 4 Cake objects in CakePacket
    {
        cArr[0] = cArr[1] = cArr[2] = cArr[3] = NULL;
    }

    ~CakePacket() {
        for(int i=0; i<4; i++) {
            if(cArr[i]) { 
                delete cArr[i];
                cArr[i] = NULL;
            }
        }
    }

    bool addCake(Cake *c) {
        for(int i=0; i<4; i++) {
            if(!cArr[i]) {
                cArr[i] = c;
                return true;
            }
        }
        return false;
    }
};

std::vectorより良い解決策は、配列の代わりにコンテナー クラス ( など) を使用することです。add メソッドを呼び出すことで、ケーキを追加できます。

CakePacket p();
p.addCake(new AppleCake(1,2));
p.addCake(new Cake(4));
于 2013-07-08T13:04:25.570 に答える