我想编写一个函数,该函数可以使用多态来初始化和返回不同类的对象。我也希望这些类具有可以通过虚函数调用的不同数据成员。我在下面写的内容可能有用。您能检查一下我是否有一些未定义的行为吗?谢谢!我担心的一件事是,当我在最后调用“删除多点”时,它不会释放“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;
}
谢谢!
最佳答案
我不得不指出Andrei Alexandrescu的对象工厂体系结构。它使您的体系结构可以扩展,而无需每次创建具体类型时都需要修改工厂。它基于“回调寄存器”,实际上在某些库中作为通用组件实现。代码如下。
Live Code Example
#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;
}