我正在设计类来表示几何对象,如矢量。我需要定义诸如加法,标量乘法,点积等方法。向量坐标可以是不同大小的整数或实数,因此需要复制对应于这些不同类型的类。
EG
class intVector
{
int X, Y;
intVector& operator+=(const intVector& A) { … }
intVector& operator*=(int A) { … }
float Norm(); // Not int
};
class floatVector
{
float X, Y;
floatVector& operator+=(const floatVector& A) { … }
floatVector& operator*=(float A) { … }
float Norm(); // Would be double for a doubleVector
};
(我还需要将二元运算符定义为函数而不是方法。)
我想避免/最小化代码重复,因此使用模板似乎是一种自然的方法。无论如何,我希望我的类看起来像普通的类,而不是模板化的类(一个选项是从模板化的类派生;另一个是类型化类的特化)。
此外,还有一个令人讨厌的约束:并非所有方法对所有数据类型都有意义,并且在某些类中根本不应该声明,或者可能存在某些参数类型的特殊情况。
在我的尝试中,我遇到了许多问题,例如需要添加许多显式实例化,难以避免无意义的成员,在基础/派生类之间转换问题......使整个设计变得痛苦。总而言之,我花了更多的代码来编写模板而不是没有!
您是否经历过类似的课程设计?有没有经典的方法来解决这个问题?
模板是处理此问题的正确方法。你可以做的是为需要表现不同的不同函数添加重载,并使用SFINAE将它们约束为它们所需的类型。使用模板我们可以将两个类组合成一个通用的Vector
类,然后使用type alias获取不同类型的具体名称。那看起来像
template<typename T>
class Vector
{
T X, Y;
Vector& operator+=(const Vector& A) { … }
Vector& operator*=(T A) { … }
template<typename U = T, std::enable_if_t<std::is_integral_v<U>, bool> = true>
correct_size_floating_point_type<U> Norm() { integer code }
template<typename U = T, std::enable_if_t<std::is_floating_point_v<U>, bool> = true>
U Norm() { floating point code }
};
using intVector = Vector<int>;
using floatVector = Vector<float>;
其中correct_size_floating_point_type
是一个模板类型,它为返回的提供的整数类型返回正确大小的浮点类型。