如何在派生类Vector3中复用基类Vector的运算符?
问题:避免Vector3派生类中运算符的重复定义
现有基类Vector的定义:
class Vector { public: Vector(const std::vector<float> &elements); static Vector add(const Vector &v1, const Vector &v2); Vector operator+(const Vector &v) const { return add(*this, v); } Vector &operator+=(const Vector &v) { *this = add(*this, v); return *this; } float operator[](size_t index) const; private: std::vector<float> _elements; };
派生类Vector3用于表示三维向量:
class Vector3 : public Vector { public: Vector3(float x, float y, float z); };
当前为了让Vector3使用基类的运算逻辑,不得不重新定义运算符:
Vector3 Vector3::operator+(const Vector3 &v) const { Vector res = Vector::operator+(v); return Vector3(res[0], res[1], res[2]); } Vector3 &Vector3::operator+=(const Vector3 &v) { Vector res = Vector::operator+=(v); *this = Vector3(res[0], res[1], res[2]); return *this; }
这段代码能正常运行,但存在重复逻辑,且疑惑为何Vector3作为固定长度3的Vector,不能直接复用基类运算符,希望找到更优实现方式。
更优实现方案
1. 改用模板基类(推荐)
核心思路是让基类通过模板参数固定向量长度,Vector3作为模板实例化产物,自然继承所有运算符且返回正确类型,完全避免重复定义。
#include <array> #include <type_traits> template<size_t N> class Vector { public: // 构造函数:接收N个float参数 template<typename... Args, typename = std::enable_if_t<sizeof...(Args) == N>> Vector(Args... args) : _elements{static_cast<float>(args)...} {} // 加法逻辑,返回同类型向量 static Vector<N> add(const Vector<N> &v1, const Vector<N> &v2) { Vector<N> res; for(size_t i = 0; i < N; ++i) { res._elements[i] = v1._elements[i] + v2._elements[i]; } return res; } Vector<N> operator+(const Vector<N> &v) const { return add(*this, v); } Vector<N> &operator+=(const Vector<N> &v) { *this = add(*this, v); return *this; } float operator[](size_t index) const { // 可添加越界检查逻辑 return _elements[index]; } private: std::array<float, N> _elements; // 固定长度用std::array比vector更高效 }; // Vector3直接作为模板别名,无需额外定义 using Vector3 = Vector<3>;
2. 改进基类add方法为模板,支持派生类构造
如果不想改动基类的非模板结构,可以将add改为模板方法,让它能返回任意继承自Vector的类型:
#include <vector> class Vector { public: Vector(const std::vector<float> &elements); // 模板版add,支持返回派生类类型 template<typename VecType> static VecType add(const VecType &v1, const VecType &v2) { std::vector<float> res_elements; res_elements.reserve(v1._elements.size()); for(size_t i = 0; i < v1._elements.size(); ++i) { res_elements.push_back(v1._elements[i] + v2._elements[i]); } // 要求派生类必须有接收std::vector<float>的构造函数 return VecType(res_elements); } Vector operator+(const Vector &v) const { return add<Vector>(*this, v); } Vector &operator+=(const Vector &v) { *this = add<Vector>(*this, v); return *this; } float operator[](size_t index) const; protected: // 修改为protected,让派生类能访问内部元素 std::vector<float> _elements; }; class Vector3 : public Vector { public: Vector3(float x, float y, float z) : Vector({x, y, z}) {} // 添加接收vector的构造函数,配合基类模板add使用 Vector3(const std::vector<float> &elements) : Vector(elements) {} // 复用基类模板,无需重复写运算逻辑 Vector3 operator+(const Vector3 &v) const { return add<Vector3>(*this, v); } Vector3 &operator+=(const Vector3 &v) { *this = add<Vector3>(*this, v); return *this; } };
3. 优化现有operator+=的实现
如果暂时不想改动基类结构,可以直接优化当前operator+=的实现,避免不必要的临时对象:
Vector3 &Vector3::operator+=(const Vector3 &v) { // 直接调用基类的+=修改当前对象的内部元素 Vector::operator+=(v); // 当前对象本身就是Vector3,无需重新构造赋值 return *this; }
这种方式减少了一次临时对象的构造和拷贝,提升了运行效率。
内容的提问来源于stack exchange,提问作者vtx22
相关产品推荐
相关产品推荐

