继承,提升基类成员

时间:2013-09-09 20:00:03

标签: c++ inheritance

鉴于以下类别:

template <typename DataType, size_t Dimensions>
class Vector : public std::array<DataType, Dimensions> {
//stuff
};

template <typename DataType>
class Vector2 : public Vector<DataType, 2> {
//2d specific stuff
};

template <typename DataType, size_t Dimensions>
class Line {
public:
  Vector<DataType, Dimensions>& min();
  Vector<DataType, Dimensions>& max();

private:
  Vector<DataType, Dimensions> m_min;
  Vector<DataType, Dimensions> m_max;
};

template <typename DataType>
class Line2 : public Line<DataType, 2> {
//2d specific stuff
};

min()上调用max()Line2时,最好的方法是什么,返回Vector2&而不是Vector&?我可以在m_min内将m_maxVector2提升为Line2吗?或者以其他方式覆盖它们并且仍然具有Line基类功能吗?

3 个答案:

答案 0 :(得分:1)

通常的做法是将模板分解为常见和特殊部分:

template <typename T, size_t N> struct LineCommon { /* ... */ };

template <typename T, size_t N> struct Line : LineCommon<T, N>
{
    Vector<T, N> & min();
    Vector<T, N> & max();
};

template <typename T> struct Line2 : LineCommon<T, 2>
{
    Vector2<T> & min();
    Vector2<T> & max();
};

答案 1 :(得分:1)

我认为Kerrek建议将部分模板特化与公共基类一起使用是明智的,但是您应该将该技术应用于Vector类型:

template <typename DataType, size_t Dimensions>
class VectorBase : public std::array<DataType, Dimensions> {
  // things common to all vectors here
};

template <typename DataType, size_t Dimensions>
class Vector : public VectorBase<DataType, Dimensions> {
   // nothing here
};

template <typename DataType>
class Vector<DataType, 2> : public VectorBase<DataType, Dimension> {
  // 2d specific stuff here, so for example:
  DataType& x() { return at(0); }
  DataType& y() { return at(1); }
};

template <typename DataType, size_t Dimensions>
class Line {
public:
  Vector<DataType, Dimensions>& min();
  Vector<DataType, Dimensions>& max();

private:
  Vector<DataType, Dimensions> m_min;
  Vector<DataType, Dimensions> m_max;
};

现在你可以做到:

Line<double, 2> myLine;
double foo = myLine.max().x();

您可以 将该技术应用于Line类,但这仅对添加特定于2D线的函数很有用,例如可能计算Voronoi图。您不需要任何Line专精化来让Line返回2D Vector - 这是自动发生的。

答案 2 :(得分:0)

稍微更新一下,这就是我要做的事情:

因为某些属于Base类的函数需要返回Vector的副本,所以我需要使用CRTP。但我真的不喜欢那个所需的骨架代码。这太复杂了。

template <typename derived>
struct test_base {
  derived baz() { return *static_cast<derived *>(this); }
};

template <int N>
  struct test : public test_base<test<N>> {
};

template <>
struct test<2> : public test_base<test<2>> {
  test bar() { return *this; }
};

int main() {
  test<1> a = {};
  test<2> b = {};

  auto c = a.baz();
  auto d = b.baz();
  auto e = b.bar();

  return 0;
}

因此,为了寻求更平坦的层次结构,我采用了一些模板技巧:

#include <type_traits>

template <int N>
struct test {
  void foo() {}

  template <int P=N>
  typename std::enable_if<P == 2 && P == N>::type bar() {}

  template <int P=N>
  typename std::enable_if<P == 3 && P == N>::type baz() {}
};

int main() {
  test<1> a = {};
  test<2> b = {};
  test<3> c = {};

  a.foo();
  b.foo();
  c.foo();

  b.bar();
  c.baz();

  return 0;
}

在我看来,这是一个更清洁的解决方案。它还允许我编写如下函数:

template <int P=N>
typename std::enable_if<P >= 2 && P == N>::type x() { return Base::operator[](0); }