在 C++ 中重载乘法运算符的正确方法(双向)
Correct way to overload the multiplication operator in C++ (both directions)
我设法理解了如何将重载运算符实现为成员函数。这种方式考虑对象(实例)总是传递 rhs 给操作员。为了让它工作,我在 class 之外定义了我的重载运算符。仅当我在头文件 (.hpp) 中定义它时它才有效。如果我将函数添加到 .cpp 文件,为什么编译器会忽略它?一段代码如下:
//class.hpp
#ifndef POINT_H_
#define POINT_H_
template<class T>
class point{
public:
point(T&x,T&y);
point<T> operator*(T& lambda);
point<T> operator=(const point<T>& P);
void print();
private:
T&x_;
T&y_;
};
#endif
//class.cpp
#include<iostream>
#include "point.hpp"
template<class T>
point<T>::point(T&x,T&y)
:
x_(x),
y_(y)
{
}
template<class T>
point<T> point<T>::operator*(T& lambda){
x_*=lambda;
y_*=lambda;
return *this;
}
template <class T>
point<T> point<T>::operator = (const point<T> & P){
this->x_=P.x_;
this->y_=P.y_;
return *this;
}
template<class T>
void point<T>::print(){
std::cout<<"X is "<<this->x_<<" Y is "<<this->y_<<"\n";
}
template class point<int>;
template class point<double>;
template<class T>
point<T> operator*(T& lambda,point<T>& P)
{
return P*lambda;
}
下面显示的最后一个函数只有在我将它添加到头文件中时才有效。
template<class T>
point<T> operator*(T& lambda,point<T>& P)
{
return P*lambda;
}
主文件是
#include<iostream>
#include "point.hpp"
int main(){
double a=3.0;
double b=4.0;
point<double> X = point<double>(a,b);
double m=3.0;
X=m*X;
X.print();
return 0;
}
编译错误为
no match for 'operator*' (operand types are 'double' and 'point') X=m*X;
如果我在头文件中重载乘法运算符,则重载可以从两个方向正常工作 doublepoint 或 pointdouble.
C++ 需要在 header(通常为 .h/.hpp)中声明一个函数,以便从不同的源文件 (.cpp) 中使用它。所以你必须声明
template<class T>
point<T> operator*(T& lambda,point<T>& P);
在您包含的 header (point.hpp) 中。
顺便说一下,您对运算符的实现是错误的,因为计算 X * m
(或 m * X
)会更改 X
本身,这通常是不需要的。所以你应该实现 operator* as
template<class T>
point<T> point<T>::operator*(T& lambda){
return point<T>(x_*lambda,y_*lambda);
}
或者您可以将 operator*= 定义为
template<class T>
point<T>& point<T>::operator*=(T& lambda){
x_*=lambda;
y_*=lambda;
return *this;
}
并执行 X*=m
而不是 X=m*X
我设法理解了如何将重载运算符实现为成员函数。这种方式考虑对象(实例)总是传递 rhs 给操作员。为了让它工作,我在 class 之外定义了我的重载运算符。仅当我在头文件 (.hpp) 中定义它时它才有效。如果我将函数添加到 .cpp 文件,为什么编译器会忽略它?一段代码如下:
//class.hpp
#ifndef POINT_H_
#define POINT_H_
template<class T>
class point{
public:
point(T&x,T&y);
point<T> operator*(T& lambda);
point<T> operator=(const point<T>& P);
void print();
private:
T&x_;
T&y_;
};
#endif
//class.cpp
#include<iostream>
#include "point.hpp"
template<class T>
point<T>::point(T&x,T&y)
:
x_(x),
y_(y)
{
}
template<class T>
point<T> point<T>::operator*(T& lambda){
x_*=lambda;
y_*=lambda;
return *this;
}
template <class T>
point<T> point<T>::operator = (const point<T> & P){
this->x_=P.x_;
this->y_=P.y_;
return *this;
}
template<class T>
void point<T>::print(){
std::cout<<"X is "<<this->x_<<" Y is "<<this->y_<<"\n";
}
template class point<int>;
template class point<double>;
template<class T>
point<T> operator*(T& lambda,point<T>& P)
{
return P*lambda;
}
下面显示的最后一个函数只有在我将它添加到头文件中时才有效。
template<class T>
point<T> operator*(T& lambda,point<T>& P)
{
return P*lambda;
}
主文件是
#include<iostream>
#include "point.hpp"
int main(){
double a=3.0;
double b=4.0;
point<double> X = point<double>(a,b);
double m=3.0;
X=m*X;
X.print();
return 0;
}
编译错误为
no match for 'operator*' (operand types are 'double' and 'point') X=m*X;
如果我在头文件中重载乘法运算符,则重载可以从两个方向正常工作 doublepoint 或 pointdouble.
C++ 需要在 header(通常为 .h/.hpp)中声明一个函数,以便从不同的源文件 (.cpp) 中使用它。所以你必须声明
template<class T>
point<T> operator*(T& lambda,point<T>& P);
在您包含的 header (point.hpp) 中。
顺便说一下,您对运算符的实现是错误的,因为计算 X * m
(或 m * X
)会更改 X
本身,这通常是不需要的。所以你应该实现 operator* as
template<class T>
point<T> point<T>::operator*(T& lambda){
return point<T>(x_*lambda,y_*lambda);
}
或者您可以将 operator*= 定义为
template<class T>
point<T>& point<T>::operator*=(T& lambda){
x_*=lambda;
y_*=lambda;
return *this;
}
并执行 X*=m
而不是 X=m*X