具有复杂构造函数的对象的c ++通用构建器方法
c++ generic builder method for object with complex constructor
我目前正在编写一个用于在场景中放置对象的小型通用库。对象的排列应根据对象内容的边界框来决定。 class 目前看起来像这样:
template<class T>
class Object {
public:
Object() = default;
Object(const T& content, const Rect& bounding_box)
: _content(content)
, _bounding_box(bounding_box) {}
private:
T _content;
Rect _bounding_box;
};
现在,要构造对象,我们需要知道边界框。当然,它取决于内容的类型 T
,计算起来可能相当复杂(即文本)。
我的想法是用户应该提供自己的 Measurer
来为他自己的内容执行此计算。然后可以通过以下方式创建一个对象:
template <class T, class Measurer>
Object create_label(const T& value, Measurer op)
{
return Object(value, op(value));
}
是否应该将此方法以某种方式纳入 Object
class(类似于政策)?我在想类似于 STL 中分配器的东西。是否有针对此类问题的通用设计模式,您将如何编写这样的 class?
另外,构造函数Object(const T& content, const Rect& bounding_box)
是否应该标记为protected
,以便用户指向create_label
方法?
我想你想看看静态成员函数。这种类型的方法不需要(或没有)要操作的对象,因此它更像是一个全局函数,但它具有像 class 方法一样的范围和可见性。
诸如 createLabel 之类的工厂方法通常在 class 中声明如下:
class Object {
public:
static Object createLabel(...);
}
现在因为这是一个静态方法你可以直接调用它而不需要实例:
Object O=Object.createLabel(...);
如果您想遵循此策略,那么您的构造函数应该是私有的或受保护的,以阻止 class 用户直接实例化它们。 (顺便说一句,这同样适用于像你这样的模板化 classes)
您可以使用多种其他策略来解决您的特定问题,这些策略可能更方便,具体取决于您的情况:
- 定义一个名为getMeasurer的抽象方法,该方法有待定义
对于每个 Object subclass - 这似乎更多地绑定了 Measurer
在代码和语义上都与 subclass 紧密相关。
- 在 class/one 方法上使用部分模板规范(这是
如果你对 c++ 不是很熟悉的话,这是相当技术性的)
- 您可以使所有对象的构造函数的签名明确包含
测量器(而不是边界框级别)
编辑:应 OP 的要求,关于部分模板解决方案的一些想法:
最直接的方法是在模板定义中简单地声明一个函数,就像这样
template<class T>
class Object {
.....
private:
BoundingBox measureMe();
}
现在因为没有为 measureMe 提供*定义&(上面是一个 声明)任何实例化的 Object 实例都将导致链接器错误,因为没有定义 MeasureMe() .
但是您为特定类型提供特定实现,因此您可以包含各种特定类型的定义:
BoundingBox Object<MyThing1>::measureMe()
{
... calculatethe size of a MyThing1
}
BoundingBox Object<MyThing2>::measureMe()
{
... calculate the size of a MyThing2
}
现在,如果您尝试实例化一个您尚未为其定义测量值的对象类型,您仍然会收到错误消息;但已知类型可以按您的意愿工作。
请记住,您仍然可以定义此函数的通用模板版本,如果没有更具体的版本可用,这可能对您有用,如果您的大多数情况使用相同的逻辑但有一些边缘异常。
为什么不添加另一个采用测量器的构造函数?
template<class T>
class Object {
public:
Object() = default;
Object(const T& content, const Rect& bounding_box)
: _content(content)
, _bounding_box(bounding_box) {}
template<class Measurer>
Object(const T& content, Measurer op) : _content(content), _bounding_box(op(content)){}
private:
T _content;
Rect _bounding_box;
};
我目前正在编写一个用于在场景中放置对象的小型通用库。对象的排列应根据对象内容的边界框来决定。 class 目前看起来像这样:
template<class T>
class Object {
public:
Object() = default;
Object(const T& content, const Rect& bounding_box)
: _content(content)
, _bounding_box(bounding_box) {}
private:
T _content;
Rect _bounding_box;
};
现在,要构造对象,我们需要知道边界框。当然,它取决于内容的类型 T
,计算起来可能相当复杂(即文本)。
我的想法是用户应该提供自己的 Measurer
来为他自己的内容执行此计算。然后可以通过以下方式创建一个对象:
template <class T, class Measurer>
Object create_label(const T& value, Measurer op)
{
return Object(value, op(value));
}
是否应该将此方法以某种方式纳入 Object
class(类似于政策)?我在想类似于 STL 中分配器的东西。是否有针对此类问题的通用设计模式,您将如何编写这样的 class?
另外,构造函数Object(const T& content, const Rect& bounding_box)
是否应该标记为protected
,以便用户指向create_label
方法?
我想你想看看静态成员函数。这种类型的方法不需要(或没有)要操作的对象,因此它更像是一个全局函数,但它具有像 class 方法一样的范围和可见性。
诸如 createLabel 之类的工厂方法通常在 class 中声明如下:
class Object {
public:
static Object createLabel(...);
}
现在因为这是一个静态方法你可以直接调用它而不需要实例:
Object O=Object.createLabel(...);
如果您想遵循此策略,那么您的构造函数应该是私有的或受保护的,以阻止 class 用户直接实例化它们。 (顺便说一句,这同样适用于像你这样的模板化 classes)
您可以使用多种其他策略来解决您的特定问题,这些策略可能更方便,具体取决于您的情况:
- 定义一个名为getMeasurer的抽象方法,该方法有待定义 对于每个 Object subclass - 这似乎更多地绑定了 Measurer 在代码和语义上都与 subclass 紧密相关。
- 在 class/one 方法上使用部分模板规范(这是 如果你对 c++ 不是很熟悉的话,这是相当技术性的)
- 您可以使所有对象的构造函数的签名明确包含 测量器(而不是边界框级别)
编辑:应 OP 的要求,关于部分模板解决方案的一些想法: 最直接的方法是在模板定义中简单地声明一个函数,就像这样
template<class T>
class Object {
.....
private:
BoundingBox measureMe();
}
现在因为没有为 measureMe 提供*定义&(上面是一个 声明)任何实例化的 Object 实例都将导致链接器错误,因为没有定义 MeasureMe() .
但是您为特定类型提供特定实现,因此您可以包含各种特定类型的定义:
BoundingBox Object<MyThing1>::measureMe()
{
... calculatethe size of a MyThing1
}
BoundingBox Object<MyThing2>::measureMe()
{
... calculate the size of a MyThing2
}
现在,如果您尝试实例化一个您尚未为其定义测量值的对象类型,您仍然会收到错误消息;但已知类型可以按您的意愿工作。
请记住,您仍然可以定义此函数的通用模板版本,如果没有更具体的版本可用,这可能对您有用,如果您的大多数情况使用相同的逻辑但有一些边缘异常。
为什么不添加另一个采用测量器的构造函数?
template<class T>
class Object {
public:
Object() = default;
Object(const T& content, const Rect& bounding_box)
: _content(content)
, _bounding_box(bounding_box) {}
template<class Measurer>
Object(const T& content, Measurer op) : _content(content), _bounding_box(op(content)){}
private:
T _content;
Rect _bounding_box;
};