C++ 如何让编译器为派生类选择方法的非模板版本?
我正在编写一个矩阵类(CMatrix),其中包含3d向量(CVector)和旋转矩阵(CRotMatrix)等派生类。我的CMatrix对象可以与另一个基于CMatrix的对象相乘,也可以与任意数值(标量)相乘。 这段代码代表了我遇到的问题的本质:C++ 如何让编译器为派生类选择方法的非模板版本?,c++,templates,inheritance,matrix,C++,Templates,Inheritance,Matrix,我正在编写一个矩阵类(CMatrix),其中包含3d向量(CVector)和旋转矩阵(CRotMatrix)等派生类。我的CMatrix对象可以与另一个基于CMatrix的对象相乘,也可以与任意数值(标量)相乘。 这段代码代表了我遇到的问题的本质: template<class T> class CMatrix { public: template<class U> const CMatrix& operator=(const CMatrix<U
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;
}
编译器以正确的方式执行此操作,但该类失去了与标量相乘的能力。我用的是msvc10。提前感谢。原因是模板运算符被视为完全匹配,而矩阵版本需要转换为父引用。因此,编译器选择模板作为更好的匹配
首先考虑如果您真的需要创建的子类,并提供适当的功能/重写。
如果您需要它们,那么我将通过使一个或两个操作都不是运算符来解决问题。通过让
运算符*
执行这两种乘法,您违反了最小意外原则,即让它根据上下文执行两种截然不同的操作。我建议这两种方法都使用命名方法,这样就很明显了,但否则我建议操作符*
使用矩阵数学,使用函数ScalarMultiply
来执行单个标量类型。原因是模板操作符被认为是完全匹配的,而矩阵版本需要转换为父引用。因此,编译器选择模板作为更好的匹配
首先考虑如果您真的需要创建的子类,并提供适当的功能/重写。
如果您需要它们,那么我将通过使一个或两个操作都不是运算符来解决问题。通过让运算符*
执行这两种乘法,您违反了最小意外原则,即让它根据上下文执行两种截然不同的操作。我建议这两种方法都使用命名方法,所以这是显而易见的,但否则我建议操作符*
使用矩阵数学,使用函数ScalarMultiply
使用单个标量类型
问题是编译器更喜欢运算符*()的模板版本。在这种情况下,有没有办法让编译器为派生的CMatrix类选择合适的方法
那是因为你告诉它的。通过标量方法进行的乘法比通过CMatrix
方法进行的乘法更通用
将您的“标量乘法”方法设置为注释中所述的方法:
CMatrix& operator*(const T & inp)
{
std::cout<<"Multiplication by a scalar."<<std::endl;
return (*this);
}
CMatrix和运算符*(常数T和inp)
{
标准::cout
问题是编译器更喜欢运算符*()的模板版本。在这种情况下,有没有办法让编译器为派生的CMatrix类选择合适的方法
那是因为你告诉它的。你的用标量
方法进行乘法比你的用CMatrix
方法进行乘法更通用
将您的“标量乘法”方法设置为注释中所述的方法:
CMatrix& operator*(const T & inp)
{
std::cout<<"Multiplication by a scalar."<<std::endl;
return (*this);
}
CMatrix和运算符*(常数T和inp)
{
std::coutWhy有从CMatrix
派生的单独的CRotMatrix
类型?对我来说似乎没有必要,因为旋转矩阵可以由普通的CMatrix
表示。我这样做是因为我希望能够以这种方式初始化旋转矩阵:然后使初始化代码成为非成员函数例如,您可以编写类似于template void InitRotMatrix(CMatrix&mat,T roll,T pitch,T yaw){}
。这样你就不必创建新类型,代码将是自文档化的。谢谢,我想我会这样做。为什么你有一个独立的CRotMatrix
类型,它派生自CMatrix
?对我来说似乎没有必要,因为旋转矩阵可以用普通的CMatrix
表示,很好。我做了这是因为我希望能够以这种方式初始化旋转矩阵:然后使初始化代码成为非成员函数
。这样,您就不必创建新类型,代码将是自文档化的。谢谢,我想我会这样做。我将此方法变得非常通用,因为我希望我的类与任何数字类型交互,而不仅仅是与实际模板类型交互。例如,矩阵*浮点。我认为我可以将此方法限制在其内部f通过将输入标量转换为实际矩阵类型:矩阵(i,j)+=(T)INSUCARAR;< /Cord>。如果编译有错误类型,它会在编译过程中出错。不知道它是不是好方法。C++对数值类型进行自动类型升级。函数期望<代码> int >代码>,提供<代码>浮点< /代码>。没问题。代码>。换句话说,CMatrix和运算符*(T inp)
将完全满足您的要求,并且它不会过于泛型,因此可以匹配所有可能的类型。我之所以将此方法设置为泛型,是因为我希望我的类能够与任何数值类型交互,而不仅仅是与实际的模板类型交互。例如,矩阵*浮点。我认为我可以通过转换将标量输入到实际矩阵类型:矩阵(i,j)+=(T)INSUCARAR;< /Cord>。如果编译有错误类型,它会在编译过程中出错。不知道它是不是好方法。C++对数值类型进行自动类型升级。函数期望<代码> int >代码>,提供<代码>浮点< /代码>。没问题。code>。换句话说,CMatrix&operator*(tinp)
将完全满足您的需要,并且它不是过于泛型,它可以匹配所有可能的类型。T