试图引用对象工厂中已删除的函数
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 还需要一个默认构造函数。所以添加它,它编译得很好!
我在编译代码时遇到下一个错误。
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 还需要一个默认构造函数。所以添加它,它编译得很好!