9

仮想クラスをかなり広範囲に使用するグラフィックス アプリケーションに取り組んでいます。それは持っています:

  • 基本的に形状のコレクションである画像クラス。

  • 純粋に仮想であり、それから継承するいくつかのクラスを持つ shape クラス:

    • サークル
    • ポリゴン
    • 矩形
  • 任意のグラフィカル フィギュア (仮想でもある) である Figure シェイプは、これから継承します。

基本的に、私の問題は、基本的に形状のコレクションを格納するために使用されている画像クラスの実装に帰着します。現在、形状を保存するためにベクターを使用していますが、ベクターがこれらの形状をインスタンス化するため、これが間違った決定であることは明らかです。これらは純粋に仮想であるため、これは適切ではありません。

以下は私の現在のコードベースです(少し要約):

class Figure {
public:
...
  virtual ~Figure();
...
};

class Shape: public Figure
{
public:
...
  virtual ~Shape() {}
  virtual Shape* clone() const = 0;
...
};

class Polygon : public Shape
{
public:
...
virtual Shape* clone() const {return new Polygon(*this);}
... 
private:
std::vector<Point> points;

};

class Picture: public Figure {
public:
...
  Picture(Graphics& gd);
  Picture (const Picture&);
  ~Picture();
  void clear();
  void add (const Shape&);
...
private:
std::vector<Shape> shapes;
Graphics* gfx;
};

//Picture implementation:
...
Picture::Picture(Graphics& gd)
{
gfx = &gd;
}


Picture::Picture(const Picture& a)
{
shapes = a.shapes;
}

Picture::~Picture() 
{
clear();
}

void Picture::clear()
{
shapes.clear();
}

void Picture::add (const Shape& shp)
{
Shape* nshp = shp.clone();
shapes.push_back(*nshp);
}
...

私が得ているエラーメッセージは、これらのほんの一握りです:

picture.cpp:33: ここからインスタンス化 /opt/local/bin/../lib/gcc/sparc-sun-solaris2.10/4.4.1/../../../../include/c++ /4.4.1/ext/new_allocator.h:105: エラー: 抽象型 'Shape' shape.h:12 のオブジェクトを割り当てることができません: 注: 次の仮想関数は 'Shape' 内で純粋であるため: shape.h:58 : note: virtual void Shape::get(std::istream&) shape.h:31: note: virtual void Shape::put(std::ostream&) const shape.h:36: note: virtual void Shape::scale (const Point&, double) shape.h:40: 注: 仮想ボイド Shape::translate(double, double) shape.h:45: 注: 仮想ボイド Shape::reflectHorizo​​ntally(double) shape.h:49: 注: virtual void Shape::reflectVertically(double) shape.h:52: 注: virtual RectangularArea Shape::boundingBox() const 形状。h:21: note: virtual Shape* Shape::clone() const shape.h:55: note: virtual void Shape::draw(Graphics&) const

では、これらの形状を保存する理想的な方法は何ですか。これらのものを保存するには、どのようなコレクションを使用する必要がありますか?

ありがとう

4

3 に答える 3

20

ポリモーフィズムが必要な場合は、ポインターまたは参照のいずれかを使用する必要があります。コンテナー (または配列) は参照を格納できないため、ポインターを使用する必要があります。

基本的に、ピクチャ クラスのベクトルを次のように変更します。

std::vector<Shape*>

他のメンバー関数を適切に変更します。

それらを値の型として保存できない/すべきではない理由は、ベクターが同種のコンテナーであるためです。つまり、1 つのタイプのデータのみを保存します (そして、 1 つのタイプのみ- サブクラスは許可されません!)。これは、ベクトルがそのデータを配列に格納するためであり、格納するオブジェクトのサイズを知る必要があります。これらのオブジェクトのサイズが異なる場合 (形状が異なる可能性があります)、それらを配列に格納することはできません。

それらをポインターとして保存すると、それらはすべて同じサイズ ( sizeof(Shape*)) になり、形状の vtable にもアクセスできるため、ポリモーフィックな動作が可能になります。

于 2010-03-07T00:04:27.457 に答える
4

共変の戻り値の型を使用します。メソッドについては、 FAQ 20.8を参照してください。cloneファクトリ メソッドを使用してShapeオブジェクトを作成することもできます。

また、抽象クラス オブジェクトのコンテナを持つことはできません。抽象クラスをインスタンス化することはできません。代わりに、派生具象オブジェクトへのポインター/参照のコンテナーを作成します。ポインタを使用している場合、それらをクリアするのはあなたの責任になることに注意してください。コンテナはメモリの割り当てを適切に解除しません。これをより効率的に処理するために、生のポインターの代わりにスマート ポインターを使用できます。上scoped_ptrを向いてshared_ptrBoostから。

于 2010-03-07T00:05:08.547 に答える