提问人:ChaoSXDemon 提问时间:7/29/2023 最后编辑:ChaoSXDemon 更新时间:7/29/2023 访问量:98
基于 C++ 中枚举值的专用类构造函数
Specialized class constructor based on enum value in C++
问:
我需要创建一个描述一组数学形状的类。假设我想要 、 和 。对于这些,我将创建一个来表示它们,并希望用户传入他们想要的形状类型并提供正确的输入。例如:Sphere
Cylinder
AABB
OBB
enum
// Shapes.h
enum ShapeType { Sphere, Cylinder, AABB, OBB, Count};
class Shape {
public:
Shape(ShapeType type, const float r, const float hl, const Vector3& minExtend, const Vector3& maxExtend);
private:
ShapeType m_Type;
float m_Radius; // for Sphere and Cylinder end caps
float m_halfLength; // for Cylinders
Vector3 m_minExtend; // for AABB or OBB
Vector3 m_maxExtend; // for AABB or OBB
Entity m_Parent; // has position, orientation and scale;
}
不理想的是,在创建 的实例时,用户被迫提供所有变量,即使他们不需要它。例如,Sphere 不会关心半长。因此,我的问题是 - 有没有办法根据值来专业化我的构造函数?例如,下面的伪代码:Shape
enum
// Shapes.h
enum ShapeType { Sphere, Cylinder, AABB, OBB, Count};
class Shape {
public:
Shape(ShapeType type = Sphere, const float r);
Shape(ShapeType type = Cylinder, const float r, const float hl);
Shape(ShapeType type = AABB, const Vector3& minExtend, const Vector3& maxExtend);
Shape(ShapeType type = OBB, const Vector3& minExtend, const Vector3& maxExtend);
// ... same as above
注意:我真的不想在这里使用继承并创建一个形状系列,因为这个类实际上只是用于在发送到另一个进程之前保存一些原始数据。
答:
3赞
fabian
7/29/2023
#1
如果提供形状类型作为参数,则无法执行此操作。毕竟给了
float r = 5;
ShapeType shape = getRandomShape(); // determine the shape to use via random number generation
Shape shape(shape, r);
编译器无法判断是否是 ;该值在运行时确定。shape
ShapeType::Sphere
如果始终直接提供常量,则有一些方法可以使用制造商参数实现与此类似的操作,该参数为对象提供模板参数,以便编译器能够使用重载解析确定正确的构造函数。ShapeType
template<ShapeType>
struct ShapeTypeTag
{};
inline constexpr ShapeTypeTag<ShapeType::Sphere> SphereType;
class Shape {
public:
Shape(ShapeTypeTag<Sphere>, const float r);
Shape(ShapeTypeTag<Cylinder>, const float r, const float hl);
Shape(ShapeTypeTag<AABB>, const Vector3& minExtend, const Vector3& maxExtend);
Shape(ShapeTypeTag<OBB>, const Vector3& minExtend, const Vector3& maxExtend);
};
...
Shape shape(SphereType, 5);
我实现这一点的首选方法是创建单独的静态成员函数以创建每个形状类型:Shape
class Shape {
template<ShapeType>
ShapeTypeTag
{
};
Shape(const float r);
Shape(const float r, const float hl);
Shape(ShapeTypeTag<AABB>, const Vector3& minExtend, const Vector3& maxExtend);
Shape(ShapeTypeTag<OBB>, const Vector3& minExtend, const Vector3& maxExtend);
public:
static Shape createSphere(float r)
{
return r;
}
static Shape createCylinder(float r, float hl)
{
return { r, hl };
}
static Shape createAABB(const Vector3& minExtend, const Vector3& maxExtend)
{
return { ShapeTypeTag<ShapeType::AABB>{}, minExtend, maxExtend };
}
static Shape createOBB(const Vector3& minExtend, const Vector3& maxExtend)
{
return { ShapeTypeTag<ShapeType::OBB>{}, minExtend, maxExtend };
}
};
...
Shape shape = Shape::createSphere(5);
评论
0赞
Retired Ninja
7/29/2023
不久前看到这个问题,回来说几乎同样的话。作为该类的理论用户,我更喜欢名称告诉我我正在创建什么的函数,而不必猜测要使用哪个构造函数以及它需要什么参数。
0赞
gast128
7/29/2023
对于此解决方案,还可以将 std::integral_constant 与原始枚举结合使用来获取不同的类型。
0赞
ChaoSXDemon
7/30/2023
要是我的调用者能调用这些静态方法就好了!由于代码库限制,我认为我必须使用构造函数,我真的很喜欢您的标记方法。感谢您提供此解决方案!如果我可以使用静态方法一,我也希望这样做。
评论