3

ポリモーフィズムを使用して、異なるクラスのオブジェクトを初期化して返すことができる関数を書きたいと思います。また、これらのクラスに、仮想関数を介して呼び出すことができるさまざまなデータ メンバーを持たせたいと考えています。私が以下に書いたことはうまくいくかもしれません。そこに未定義の動作があるかどうかを確認できますか? ありがとうございました!ひとつ気になるのは、最後に「delete polypoint」を呼び出すと「CRectangle」固有のデータメンバ「scale」が解放されないことです。コードが機能しない場合、機能させる方法はありますか?

class CPolygon {
  protected:
    int width, height;
  public:
    void set_values (int a, int b)
      { width=a; height=b; }
    virtual int area ()
      { return (0); }
  };

class CRectangle: public CPolygon {
  public:
    int scale;
    int area ()
      { return (width * height * scale ); }
  };

CPolygon *polytestinner()
{
    CPolygon *polypoint = 0;

    int consoleinput = 2;
    if (consoleinput>1)
    {
        CRectangle *rectpoint = new CRectangle();
        rectpoint->scale = 4;
        polypoint = rectpoint;
    }
    polypoint->set_values(3,4);
    return polypoint;
}

void polytest()
{
    CPolygon *polypoint = polytestinner();
    gstd::print<int>(polypoint->area());    
    delete polypoint;
}

int main()
{
    polytest();
    return 0;
}

ありがとうございました!

4

3 に答える 3

4

Andrei Alexandrescu のオブジェクト ファクトリ アーキテクチャを指摘しなければならないと感じています。具象型を作成するたびにファクトリを変更することなく、アーキテクチャを拡張できます。これは「コールバック レジスタ」に基づいており、実際には一部のライブラリで汎用コンポーネントとして実装されています。コードは以下です。

ライブコードの例

#include<map>
#include<iostream>
#include<stdexcept>

// your typical base class
class Shape {
 public:
  virtual void Draw() const = 0;
  // virtual destructor allows concrete types to implement their own
  // destrucion mechanisms
  virtual ~Shape() {} 
};

// this factory architecture was suggested by Andrei Alexandrescu in
// his book "Modern C++ Design" --- read it to get the full
// explanation (and a more generic implementation); this is just an
// example
class ShapeFactory {
 public:
  // this typedef allows to "name" arbitrary functions which take no
  // arguments and return a pointer to a Shape instance
  typedef Shape* (*CreateShapeCallback)();

  Shape* CreateShape(int ShapeId) {
    // try to find the callback corresponding to the given shape id;
    // if no shape id found, throw exception
    CallbackMap::const_iterator it = m_callbacks.find(ShapeId);
    if(it == m_callbacks.end()) {
      throw std::runtime_error("unknown shape id");
    } else {
      // create the instance using the creator callback
      return (it->second)();
    }    
  }

  bool RegisterShape(int ShapeId, CreateShapeCallback Creator) {
    // returns true if shape was registered; false if it had already
    // been registered
    return m_callbacks.insert(CallbackMap::value_type(ShapeId, Creator)).second;
  }

  bool UnRegisterShape(int ShapeId) {
    // returns true if shape was unregistered, false if it was not
    // registered in the first place
    return m_callbacks.erase(ShapeId) == 1;
  }

 private:
  // the typedef simplifies the implementation
  typedef std::map<int, CreateShapeCallback> CallbackMap;
  // the callbacks are stored in a map int->callback (see typedef
  // above)
  CallbackMap m_callbacks;
};


// create some concrete shapes... you would do this in other CPP files
class Line : public Shape {
 public:
  void Draw() const {
    std::cout<<"Drawing a line"<<std::endl;
  }
};

// another concrete shape...
class Circle : public Shape {
 public:
  void Draw() const {
    std::cout<<"Drawing a circle"<<std::endl;
  }
};
// ... other concrete shapes...

enum ShapeIds {LINE=1, CIRCLE, COUNT};
Shape* CreateLine() { return new Line; }
Shape* CreateCircle() { return new Circle; }


int main() {
  // suppose this is the "singleton" instance for the ShapeFactory
  // (this is an example! Singletons are not implemented like this!)  
  ShapeFactory *factory = new ShapeFactory;
  factory->RegisterShape(ShapeIds::LINE, CreateLine);
  factory->RegisterShape(ShapeIds::CIRCLE, CreateCircle);

  Shape* s1 = factory->CreateShape(ShapeIds::CIRCLE);
  Shape* s2 = factory->CreateShape(ShapeIds::LINE);
  s1->Draw();
  s2->Draw();
  // will throw an error
  try {
    Shape *s3 = factory->CreateShape(-1);
    s3->Draw();    
  } catch(const std::exception& e) {
    std::cout<<"caught exception: "<<e.what()<<std::endl;    
  }
  return 0;
}
于 2013-04-12T18:46:16.397 に答える
3

CPolygon仮想デストラクタが必要です:

virtual ~CPolygon() {}
于 2013-04-12T17:44:24.073 に答える
1

コードに次のものがundefined behaviorあります。

  CPolygon *polypoint;
  delete polypoint;

base class pointer仮想デストラクタがないときにa を削除すると、未定義の動作が発生します。

この場合、コンパイラはデフォルトのデストラクタを生成しますが、CPolygonクラスとクラスにはデストラクタがありませんが、 . したがって、少なくとも基本クラスの 、つまり を定義する必要があります。CRectanglenot virtual by defaultvirtual destructorCPolygon

于 2013-04-12T17:47:39.280 に答える