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格式轉換一樣是有危險的,以上。
留言列表