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

Attempting to reference a deleted function in objects factory

我在编译代码时遇到下一个错误。

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 例如:

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:

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。这个classes的所有方法都有实现。

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);
};

这一行:

classes[id] = &instantiator<Derived>;

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

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

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

Point2d points[2];

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

Point2d(double xx, double yy);

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

要实现此功能,您必须向 Point2d 添加默认构造函数,或者允许通过 Square 的构造函数将参数传递给 points。可能后者最有意义。

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

修改后的使用示例:

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); 
    } 

不幸的是,数组不能在内存初始化器中初始化,所以 Point2d 还需要一个默认构造函数。所以添加它,它编译得很好!