我有以下类层次结构:
template<typename T>
class GridMetric{
virtual GridMetric* getNeighbors(T value) = 0;
};
template<size_t N, typename T, typename Derived>
class MatrixBase : public GridMetric<T>{
virtual MatrixBase<N,T,Derived>* getNeighbors(T value){return nullptr;}
};
template<size_t N, typename T>
class MatrixND : public MatrixBase<N,T,MatrixND<N,T>>{
virtual MatrixND<2,T>* getNeighbors(T value){ /* ... */}
};
template<typename T>
class MatrixND<2,T> : public MatrixBase<2,T,MatrixND<2,T>>{
virtual MatrixND<2,T>* getNeighbors(T value){ /* ... */}
};
template<typename T>
class Vector : public GridMetric<T>{
virtual MatrixND<2,T>* getNeighbors(T value){ /* ... */}
};
所以我的抽象类GridMetric有两个派生类,Vector和MatrixBase。 My Matrix Base类具有crtp样式派生类MatrixND,并且有一个N = 2的MatrixND专门化。
每个类都应具有虚函数getNeighbors以返回MatrixND&lt; 2,T&gt;指针。
一切正常,但MatrixND类抱怨MatrixND&lt; 2,T&gt;是一个无效的协变返回类型:
error: invalid covariant return type for ‘MatrixND<2ul, T>* MatrixND<N, T>::getNeighbors(T&) [with long unsigned int N = 3ul; T = double]’
virtual MatrixND<2,T>* getNeighbors(T& in){
我的第一个问题是为什么以及如何处理?由于MatrixND&lt; 2,T&gt;继承自MatrixBase!
我的第二个问题:这是不好的设计,因为我总是会返回原始指针?我读了表达式返回new obj ..很多,而且这显然是糟糕的设计。还有其他可能性来实现同样的目标吗?
编辑:所以,经过一段时间后,我意识到,最初的计划不会成功,我通过模板化课程找到了一个更容易的解决方案,我想在那里使用那些类。
无论如何,问题在于,为什么专门的MatrixND类不能成为一般MatrixND类中的协变返回类型。我没有发现任何说不允许的事情。
答案 0 :(得分:1)
MatrixND<2,T>
,基本情况,无需解释。Vector<T>
继承自GridMetric<T>
,因此任何来自GridMetric<T>
(包括此处MatrixND<2,T>
)的内容都可以。但是,一般形式MatrixND<N,T>
(N
!= 2)继承自MatrixBase<N,T,MatrixND<N,T>>
,它将虚函数重新定义为:
virtual MatrixBase<N,T,Derived>* getNeighbors(T value){return nullptr;}
强制MatrixND<N,T>
的返回类型现在(至少)从MatrixBase<N,T,MatrixND<N,T>>
派生。
不是GridMetric<T>
(对于Vector<T>
)或MatrixBase<2,T,MatrixND<2,T>>
(对于专业化MatrixND<2,T>
),而是:MatrixBase<N,T,MatrixND<N,T>>
,(N
! = 2)。
为什么这不是协变返回类型?因为MatrixND<2,T>
!= 2时MatrixBase<N,T,MatrixND<N,T>>
不会从N
继承。
删除MatrixBase<N,T,MatrixND<N,T>>
中的功能重新定义或将其返回类型更改为GridMetric<T>
,这样就可以了(因为MatrixND<2,T>
继承自GridMetric<T>
)。