如何解决C ++基类构造函数,将派生类作为参数?
用例:
-
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
//...
};
}
注意:实际的类包含更多内容,但我将其简化为我认为在这里最重要的代码。
问题是我无法实现一种可以从Vector
构造Vector2D
的方式,请参见下面的代码。所有其他情况都可以正常工作。
// 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,int> h{g};
当然,更普遍的问题是继承是否是构造这些类的正确方法。但是我希望Vector2D
具有Vector
的所有功能以及Vector
没有的其他功能。
解决方法
您的Vector
类具有两个构造函数:一个模板(用于值)和默认的复制构造函数。
问题:首选复制构造函数,但前提是完全匹配。
因此,用b
初始化a
mu::Vector<2,int> a{1,2};
mu::Vector<2,int> b{a};
首选复制构造函数,因为a
是完全匹配
但是,用h
初始化g
mu::Vector2D<int> g{1,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>
的构造函数。它将拦截不是副本的所有构造,并且派生类对象的构造不是。这是因为从派生到基数的转换是一次转换,并且模板构造函数不需要转换,因此是更好的匹配。
如果参数适合于构造std::array
成员,则希望限制包罗万象的构造函数仅包括在重载解析中。这是SFINAE的标准应用程序。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。