繁体   English   中英

以派生类为参数的 C++ 基类构造函数 (?)

[英]C++ base class constructor taking derived class as argument (?)

用例:

  • Vector类(实现一些数学)和一个派生的Vector2D
  • 理想情况下,两个类都应该允许彼此“复制构造”

Vector

namespace mu {
template<std::size_t N, typename T>
class Vector {
  public:
  // ...

  template <typename... TArgs>
  Vector(TArgs... args) : data({args...}) {}

  Vector(const Vector &other) = default; // copy constructor

  // ...
  protected:
    std::array<T, N> data;
};
}

Vector2D

namespace mu {
template<typename T>
class Vector2D : public Vector<2,T> {

  public:

  using Vector<2, T>::Vector; // inherit base class constructors

  Vector2D(const Vector<2, T>& other) : Vector<2, T>(other) {}

  // Vector2D specific functions, e.g. rotation
  //...

};
}

注意:实际的类包含更多内容,但我将其浓缩为我认为在这里最重要的代码。

问题是我无法实现一种可以从Vector2D构造VectorVector2D ,请参阅下面的代码。 所有其他情况都可以正常工作。

// Example 1 (compiles)
mu::Vector<2, int> a{1, 2};
mu::Vector<2, int> b{a};

// Example 2 (compiles)
mu::Vector2D<int> c{1, 2};
mu::Vector2D<int> d{c};

// Example 3 (compiles)
mu::Vector<2, int> e{1, 2};
mu::Vector2D<int> f{e};

// Example 4 (doesn't compile)  <-- how to get this to work?
mu::Vector2D<int> g{1, 2};
mu::Vector<2, int> h{g};

当然,更普遍的问题是继承是否是构建这些类的正确方法。 但是我希望Vector2D具有Vector所有功能以及Vector没有的附加功能。

您的Vector类有两个构造函数:一个模板(用于值)和默认的复制构造函数。

问题:复制构造函数是首选,但前提是存在完全匹配。

所以,用a初始化b

mu::Vector<2, int> a{1, 2};
mu::Vector<2, int> b{a};

首选复制构造函数,因为a是完全匹配的

但是,用g初始化h

mu::Vector2D<int> g{1, 2};
mu::Vector<2, int> h{g};

g可以转换为mu::Vector<2, int>不是完全匹配,因此模板构造函数是首选,但模板构造函数不兼容。

一种可能的解决方案:当只有一个参数并且该参数从mu::Vector派生时,SFINAE 禁用模板构造函数。

例如

template <typename... TArgs,
          typename std::enable_if_t<sizeof...(TArgs) == N
                                or (not std::is_base_of_v<Vector, TArgs> && ...), int> = 0>
Vector(TArgs const & ... args) : data({args...}) {}

撇开继承对这个特定任务的适用性不谈,失败的直接原因是template <typename... TArgs>构造函数。 它将拦截每个不是副本的构造——并且从派生类对象构造不是副本。 这是因为从 Derived 到 Base 的转换是一种转换,而模板构造函数不需要转换,所以是更好的匹配。

如果参数适合构造std::array成员,您希望将全部构造函数限制为仅包含在重载决议中。 这是 SFINAE 的标准应用程序。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM