如何让编译器为派生类选择方法的非模板版本

How to make the compiler choose the non-template version of a method for derived classes?

本文关键字:方法 版本 选择 编译器 派生      更新时间:2023-10-16

我正在编写一个矩阵类(CMatrix(,其中包含诸如三维向量(CVector(和旋转矩阵(CRotMatrix(之类的派生类。我的CMatrix对象可以与另一个基于CMatrix的对象相乘,也可以与任何数值(标量(相乘。这段代码代表了我遇到的问题的本质:

template<class T> class CMatrix
{
public:
    template<class U> const CMatrix& operator=(const CMatrix<U> &inp){return (*this);}
    CMatrix& operator*(const CMatrix &inp) 
    {   
        cout<<"Multiplication by CMatrix"<<endl;
        return (*this);
    }
    template<class U> 
    CMatrix& operator*(const U &inp)
    {
        cout<<"Multiplication by a scalar."<<endl;
        return (*this);
    }
};
template<class T> class CVector: public CMatrix<T>{};
template<class T> class CRotMatrix: public CMatrix<T>{};
int main()
{
    CMatrix<int> foo1;
    CMatrix<int> foo2;
    CVector<int> dfoo1;
    CRotMatrix<int> dfoo2;
    foo1 = foo1*foo2;   //calls CMatrix method
    foo1 = foo1*5;      //calls scalar method
    foo1 = foo1*dfoo2;  //calls scalar method, shoud be CMatrix
    foo1 = dfoo2*dfoo1; //calss scalar method, shoud be CMatrix
    return 0;
}

问题是编译器更喜欢运算符*((的模板版本。在这种情况下,有什么方法可以让编译器为派生的CMatrix类选择正确的方法吗?如果我切断这种方法

CMatrix& operator*(const U &inp)

编译器以正确的方式执行,但类失去了与标量相乘的能力。我在用msvc10。提前谢谢。

原因是模板运算符被认为是完全匹配的,而矩阵版本需要转换为父引用。因此,编译器选择模板作为更好的匹配。

首先考虑您是否真的需要创建的子类,以及它们是否提供了适当的功能/覆盖。

如果你需要它们,那么我会通过使其中一个或两个操作而不是运算符来解决问题。让operator*做两种乘法,违反了最小惊喜原则,让它根据上下文做两种截然不同的事情。我建议两者都使用命名方法,所以这是显而易见的,但除此之外,我建议operator*为矩阵数学,函数ScalarMultiply为单个标量类型。

问题是编译器更喜欢运算符*((的模板版本。在这种情况下,有什么方法可以让编译器为派生的CMatrix类选择正确的方法吗?

这是因为你告诉它。你的Multiplication by a scalar方法比你的Multiplication by CMatrix方法更通用。

让你的"标量乘"方法成为评论所说的:

CMatrix& operator*(const T & inp)
{   
    std::cout<<"Multiplication by a scalar."<<std::endl;
    return (*this);
}   

附录
您的template<class U> CMatrix& operator*(const U &inp)是如此通用,以至于它匹配任何。多重std::istream:没问题。它打印Multiplication by a scalar.你希望你与标量的乘积是有限制的,而不是任何随机类型的包罗万象。