鱼C论坛

 找回密码
 立即注册
查看: 472|回复: 2

[已解决]C++ 模板类特化中的变量问题

[复制链接]
发表于 2023-10-15 20:12:18 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
我有这一段代码:
  1. #include <array>
  2. template <unsigned short dimensions>
  3. class Vector
  4. {
  5.         public:
  6.                 static const unsigned short dimension = dimensions;
  7.                 std::array<double, dimensions> values;
  8.                 Vector() = default;
  9.                 Vector(const Vector &) = default;
  10.                 Vector(Vector &&) = default;
  11.                 Vector(std::array<double, dimensions> values)
  12.                 {
  13.                         this->values = values;
  14.                 };
  15.                 Vector<dimensions> & operator=(const Vector<dimensions> &) = default;
  16.                 Vector<dimensions> operator+(const Vector<dimensions> &other) const
  17.                 {
  18.                         Vector<dimensions> result;
  19.                         for (unsigned short index = 0; index < dimensions; index++)
  20.                         {
  21.                                 result.values[index] = this->values[index] + other.values[index];
  22.                         };
  23.                         return result;
  24.                 };
  25.                 Vector<dimensions> operator+(const double other) const
  26.                 {
  27.                         Vector<dimensions> result;
  28.                         for (unsigned short index = 0; index < dimensions; index++)
  29.                         {
  30.                                 result.values[index] = this->values[index] + other;
  31.                         };
  32.                         return result;
  33.                 };
  34.                 Vector<dimensions> operator-() const
  35.                 {
  36.                         Vector<dimensions> result;
  37.                         for (unsigned short index = 0; index < dimensions; index++)
  38.                         {
  39.                                 result.values[index] = -this->values[index];
  40.                         };
  41.                         return result;
  42.                 };
  43.                 Vector<dimensions> operator-(const Vector<dimensions> &other) const
  44.                 {
  45.                         return (*this) + -other;
  46.                 };
  47.                 Vector<dimensions> operator-(const double other) const
  48.                 {
  49.                         return *this + -other;
  50.                 };
  51.                 Vector<dimensions> operator*(const double other) const
  52.                 {
  53.                         Vector<dimensions> result;
  54.                         for (unsigned short index = 0; index < dimensions; index++)
  55.                         {
  56.                                 result.values[index] = this->values[index] * other;
  57.                         };
  58.                         return result;
  59.                 };
  60.                 Vector<dimensions> operator/(const double other) const
  61.                 {
  62.                         return *this * (1.0 / other);
  63.                 };
  64.                 double dot(const Vector<dimensions> &other) const
  65.                 {
  66.                         double result = 0;
  67.                         for (unsigned short index = 0; index < dimensions; index++)
  68.                         {
  69.                                 result += this->values[index] * other.values[index];
  70.                         };
  71.                         return result;
  72.                 };
  73.                 double length() const
  74.                 {
  75.                         return sqrt(this->dot(*this));
  76.                 };
  77.                 Vector<dimensions> length(const int scale) const
  78.                 {
  79.                         return *this / (this->length() / scale);
  80.                 };
  81.                 double angle(const Vector<dimensions> &other) const
  82.                 {
  83.                         return acos(this->dot(other) / (this->length() * other.length()));
  84.                 };
  85. };

  86. template <>
  87. class Vector<3>
  88. {
  89.         public:
  90.                 Vector<3> operator*(const Vector<3> &other) const
  91.                 {
  92.                         Vector<3> result;
  93.                         for (unsigned short index = 0; index < 3; index++)
  94.                         {
  95.                                 result.values[index] = this->values[(index + 1) % 3] * other.values[(index + 2) % 3] - this->values[(index + 2) % 3] * other.values[(index + 1) % 3];
  96.                         };
  97.                         return result;
  98.                 };
  99. };
复制代码

我对这个 Vector 进行特化,使其能够完成仅提供三维支持的叉乘,但是编译器报错说在特化中 'const class Vector<3>' has no member named 'values' ,难道特化不保有模板的函数和变量吗?如果不保有,那么怎么修改才能做到减少代码冗余;如果保有,那么这里为什么会报错,又怎么解决?
最佳答案
2023-10-15 20:12:55
在C++中,模板特化并不保留原模板的成员函数和变量。当你为模板类进行特化时,你实际上是在为特定的模板参数创建一个全新的类定义。这就是为什么在你的特化版本的 Vector<3> 中,编译器无法找到 values 成员的原因。

如果你希望在特化版本中保留一些通用的成员和函数,你可以考虑使用模板类的继承。例如,你可以创建一个基础的 VectorBase 类,然后让 Vector 继承自 VectorBase。这样,你就可以在 VectorBase 中定义通用的成员和函数,然后在 Vector 的特化版本中添加或覆盖特定的成员和函数。

以下是一个简单的示例:

  1. template <unsigned short dimensions>
  2. class VectorBase {
  3. public:
  4.     static const unsigned short dimension = dimensions;
  5.     std::array<double, dimensions> values;
  6.     // ... 其他通用的成员和函数 ...
  7. };

  8. template <unsigned short dimensions>
  9. class Vector : public VectorBase<dimensions> {
  10.     // ... 特定的成员和函数 ...
  11. };

  12. template <>
  13. class Vector<3> : public VectorBase<3> {
  14. public:
  15.     Vector<3> operator*(const Vector<3> &other) const {
  16.         Vector<3> result;
  17.         for (unsigned short index = 0; index < 3; index++) {
  18.             result.values[index] = this->values[(index + 1) % 3] * other.values[(index + 2) % 3] - this->values[(index + 2) % 3] * other.values[(index + 1) % 3];
  19.         };
  20.         return result;
  21.     };
  22. };
复制代码


这样,Vector<3> 就可以访问 VectorBase<3> 中定义的 values 成员了。同时,你也可以在 Vector<3> 中添加或覆盖特定的成员和函数,以实现三维向量的特殊操作。
请注意,本回答来自GPT-4
如果问题已经解决,请设置最佳答案
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-10-15 20:12:55 | 显示全部楼层    本楼为最佳答案   
在C++中,模板特化并不保留原模板的成员函数和变量。当你为模板类进行特化时,你实际上是在为特定的模板参数创建一个全新的类定义。这就是为什么在你的特化版本的 Vector<3> 中,编译器无法找到 values 成员的原因。

如果你希望在特化版本中保留一些通用的成员和函数,你可以考虑使用模板类的继承。例如,你可以创建一个基础的 VectorBase 类,然后让 Vector 继承自 VectorBase。这样,你就可以在 VectorBase 中定义通用的成员和函数,然后在 Vector 的特化版本中添加或覆盖特定的成员和函数。

以下是一个简单的示例:

  1. template <unsigned short dimensions>
  2. class VectorBase {
  3. public:
  4.     static const unsigned short dimension = dimensions;
  5.     std::array<double, dimensions> values;
  6.     // ... 其他通用的成员和函数 ...
  7. };

  8. template <unsigned short dimensions>
  9. class Vector : public VectorBase<dimensions> {
  10.     // ... 特定的成员和函数 ...
  11. };

  12. template <>
  13. class Vector<3> : public VectorBase<3> {
  14. public:
  15.     Vector<3> operator*(const Vector<3> &other) const {
  16.         Vector<3> result;
  17.         for (unsigned short index = 0; index < 3; index++) {
  18.             result.values[index] = this->values[(index + 1) % 3] * other.values[(index + 2) % 3] - this->values[(index + 2) % 3] * other.values[(index + 1) % 3];
  19.         };
  20.         return result;
  21.     };
  22. };
复制代码


这样,Vector<3> 就可以访问 VectorBase<3> 中定义的 values 成员了。同时,你也可以在 Vector<3> 中添加或覆盖特定的成员和函数,以实现三维向量的特殊操作。
请注意,本回答来自GPT-4
如果问题已经解决,请设置最佳答案
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-10-15 20:13:44 | 显示全部楼层
在模板类特化中,只有特化的部分会被编译器处理,其他部分将被忽略。因此,在 Vector<3> 的特化中,只有特化的部分会被编译器处理,而原始模板中的成员变量 values 并不会被保留。

要解决这个问题,可以使用继承来避免代码冗余。首先,将原始模板类中的所有成员函数和变量都放在一个基类中,然后在特化中继承这个基类并添加新的成员函数和变量。这样,特化中就可以使用基类中的成员变量 values 了。

以下是修改后的代码:

  1. #include <array>
  2. #include <cmath>

  3. template <unsigned short dimensions>
  4. class VectorBase
  5. {
  6. public:
  7.     static const unsigned short dimension = dimensions;
  8.     std::array<double, dimensions> values;
  9.     VectorBase() = default;
  10.     VectorBase(const VectorBase &) = default;
  11.     VectorBase(VectorBase &&) = default;
  12.     VectorBase(std::array<double, dimensions> values)
  13.     {
  14.         this->values = values;
  15.     };
  16.     VectorBase<dimensions> &operator=(const VectorBase<dimensions> &) = default;
  17.     VectorBase<dimensions> operator+(const VectorBase<dimensions> &other) const
  18.     {
  19.         VectorBase<dimensions> result;
  20.         for (unsigned short index = 0; index < dimensions; index++)
  21.         {
  22.             result.values[index] = this->values[index] + other.values[index];
  23.         };
  24.         return result;
  25.     };
  26.     VectorBase<dimensions> operator+(const double other) const
  27.     {
  28.         VectorBase<dimensions> result;
  29.         for (unsigned short index = 0; index < dimensions; index++)
  30.         {
  31.             result.values[index] = this->values[index] + other;
  32.         };
  33.         return result;
  34.     };
  35.     VectorBase<dimensions> operator-() const
  36.     {
  37.         VectorBase<dimensions> result;
  38.         for (unsigned short index = 0; index < dimensions; index++)
  39.         {
  40.             result.values[index] = -this->values[index];
  41.         };
  42.         return result;
  43.     };
  44.     VectorBase<dimensions> operator-(const VectorBase<dimensions> &other) const
  45.     {
  46.         return (*this) + -other;
  47.     };
  48.     VectorBase<dimensions> operator-(const double other) const
  49.     {
  50.         return *this + -other;
  51.     };
  52.     VectorBase<dimensions> operator*(const double other) const
  53.     {
  54.         VectorBase<dimensions> result;
  55.         for (unsigned short index = 0; index < dimensions; index++)
  56.         {
  57.             result.values[index] = this->values[index] * other;
  58.         };
  59.         return result;
  60.     };
  61.     VectorBase<dimensions> operator/(const double other) const
  62.     {
  63.         return *this * (1.0 / other);
  64.     };
  65.     double dot(const VectorBase<dimensions> &other) const
  66.     {
  67.         double result = 0;
  68.         for (unsigned short index = 0; index < dimensions; index++)
  69.         {
  70.             result += this->values[index] * other.values[index];
  71.         };
  72.         return result;
  73.     };
  74.     double length() const
  75.     {
  76.         return std::sqrt(this->dot(*this));
  77.     };
  78.     VectorBase<dimensions> length(const int scale) const
  79.     {
  80.         return *this / (this->length() / scale);
  81.     };
  82.     double angle(const VectorBase<dimensions> &other) const
  83.     {
  84.         return std::acos(this->dot(other) / (this->length() * other.length()));
  85.     };
  86. };

  87. template <unsigned short dimensions>
  88. class Vector : public VectorBase<dimensions>
  89. {
  90. public:
  91.     using VectorBase<dimensions>::VectorBase;
  92. };

  93. template <>
  94. class Vector<3> : public VectorBase<3>
  95. {
  96. public:
  97.     Vector<3> operator*(const Vector<3> &other) const
  98.     {
  99.         Vector<3> result;
  100.         for (unsigned short index = 0; index < 3; index++)
  101.         {
  102.             result.values[index] = this->values[(index + 1) % 3] * other.values[(index + 2) % 3] - this->values[(index + 2) % 3] * other.values[(index + 1) % 3];
  103.         };
  104.         return result;
  105.     };
  106. };
复制代码


在这个修改后的代码中,VectorBase 类包含了原始模板中的所有成员函数和变量,Vector 类和 Vector<3> 类继承了 VectorBase 类并添加了新的成员函数。这样,Vector<3> 就可以使用基类中的成员变量 values 了。

希望这个解决方案能够帮到你!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-5-20 08:34

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表