试图在对象工厂中引用已删除的函数

时间:2015-08-02 10:22:17

标签: c++ oop templates factory-pattern

编译代码时出现下一个错误。

Error   C2280   'Square::Square(void)': attempting to reference a deleted function  objectfactory.h 11

我有下一个对象工厂,对象:

template<class ID, class Base, class ... Args> class GenericObjectFactory {
private:
    typedef Base* (*fInstantiator)(Args ...);
    template<class Derived> static Base* instantiator(Args ... args) {
        return new Derived(args ...);
    }
    std::map<ID, fInstantiator> classes;

public:
    GenericObjectFactory() {}
    template<class Derived> void add(ID id) {
        classes[id] = &instantiator<Derived>;
    }
    fInstantiator get(ID id) {
        return classes[id];
    }
};

基类,例如:

class BaseFigure
{
private:
    BaseFigure(const BaseFigure&);
    int m_params_num;
public:
    BaseFigure() : m_params_num(0) {};
    virtual void draw(WDraw &drawer)=0;
    virtual void boundingBox(WDraw &drawer) = 0;
    virtual ~BaseFigure() {};
};

来自BaseFigure的派生类:

class Square :
    public BaseFigure
{
private:
    Point2d points[2];
public:
    std::string type();
    void draw(WDraw &drawer);
    void boundingBox(WDraw &drawer);
    ~Square();
};

下面的方形实现:

 void Square::draw(WDraw &drawer) {
    Point2d cournerSecond(points[0].x(), points[1].y()), cournerFour(points[1].x(), points[0].y());
    drawer.drawSegment(points[0], cournerSecond);
    drawer.drawSegment(cournerSecond, points[1]);
    drawer.drawSegment(points[1], cournerFour);
    drawer.drawSegment(cournerFour, points[0]);
}
void Square::boundingBox(WDraw &drawer) {
    this->boundingBox(drawer);
}

使用示例:

GenericObjectFactory<std::string , BaseFigure> figureFactory;
figureFactory.add<Square>("sq");
BaseFigure *sq = figureFactory.get("sq")();

我无法理解,错误在哪里? P.S添加了Point2D和WDraw。这个类的所有方法都有实现。

class Point2d
{
public:
    Point2d(double xx, double yy);
    virtual ~Point2d(void);
    double x() const { return m_dX; }
    double y() const { return m_dY; }
private:
    double m_dX;
    double m_dY;
};
class WDraw
{    
public:
    WDraw(void);
    virtual ~WDraw(void);
    virtual void drawSegment(const Point2d& p1, const Point2d& p2);
};

2 个答案:

答案 0 :(得分:4)

这一行:

classes[id] = &instantiator<Derived>;

设置实例化器以使用此实例化函数:

static BaseFigure* instantiator() {
    return new Square();
}

Square不是默认构造的,因为它的成员:

Point2d points[2];

不是默认构造的,因为它有一个用户声明的非默认构造函数:

Point2d(double xx, double yy);

因此错误。隐式声明的Point2d默认构造函数被声明为已删除,这使得隐式声明的Square默认构造函数也被声明为已删除。

要完成这项工作,您必须向Point2d添加默认构造函数,或者允许通过Square的构造函数将参数传递到{{1} }}。可能后者最有意义。

答案 1 :(得分:0)

巴里已经回答了根本原因。对于记录,这里使用非常好的变量参数模板作为通用构造函数的解决方案:

修改使用示例:

GenericObjectFactory<std::string, BaseFigure, Point2d, double> figureFactory; //<===== A square could be constructed with top left point + width
figureFactory.add<Square>("sq");
BaseFigure *sq = figureFactory.get("sq")(Point2d(1.0,2.0), 2.0);  //<===== Instatiate with right arguments

然后错误消息清楚地表明找不到合适的构造函数。让我们添加它:

    Square(Point2d tl, double w) 
    { 
        points[0] = tl; 
        points[1] = Point2d(tl.x()+w, tl.y()+w); 
    } 

遗憾的是,数组不能在mem-initializer中初始化,因此Point2d也需要一个默认的构造函数。所以添加它,它编译好!