class Shape

  {

  public:

    virtual ~Shape() = 0;

  };

  inline Shape::~Shape() {}

  class Polygon : public Shape

  {

  };
Polygon *createPolygon() { return new Polygon; }

reg()
函數中用了下面這句來註冊函數

factory.Register(1, reinterpret_cast<Shape* (*)()>(createPolygon));

他在註冊函數時用了reinterpret_cast然後我用,

int a;

factory.Register(1, reinterpret_cast<Shape* (*)()>(&a));

來編譯,一樣會過,但是執行期錯誤了,這樣會有個隱憂,如果有人餵不對的型別那不就錯了嗎?而且還檢查不出來,我的建議是

Shape *createPolygon() { return new Polygon; }

傳回Shape *,然後轉型改成

factory.Register(1, createPolygon);

因為虛擬函數的實作本來就不能事先知道,也不需要知道,只要呼叫Shape的虛擬函式用的是Polygon的實作就好了。

為了證明是可行的,我在Shape加了out的虛擬函式,並在三種型別中輸出。

class Shape

  {

  public:

    virtual void out()=0;

    virtual ~Shape() = 0;

  };

  inline Shape::~Shape() {}

  class Polygon : public Shape

  {

       void out()

       {

           std::cout << "Polygon";

       }

  };

  class Line : public Shape

  {

       void out()

       {

           std::cout << "Line";

       }

  };

  class Circle : public Shape

  {

       void out()

       {

           std::cout << "Circle";

       }

  };

  Shape *createPolygon() { return new Polygon; }

  Shape *createLine() { return new Line; }

  Shape *createCircle() { return new Circle; }

在原來的測試碼加入使用out的程式碼。

s = factory.CreateObject(1);

    s->out();

    delete s;

    bool test1=s!=NULL;

    s = factory.CreateObject(2);

    s->out();

    delete s;

    bool test2=s!=NULL;

    s = factory.CreateObject(3);

    s->out();

    delete s;

    bool test3=s!=NULL;

發現是可行的,根據索引從虛擬工廠得到的物件都可以使用。

總之reinterpret_cast跟單純的c格式轉換一樣是有危險的,以上。

讓地獄深紅的天亮 發表在 痞客邦 PIXNET 留言(0) 人氣()