为什么需要使用 friend 修饰符来重载 C++ 中的 * 运算符?
Why is it necessary to use the friend modifier for overloading the * operator in C++?
我决定在学习C++期间将矩阵运算作为练习来实现。我选择了基于模板化 class 的方法(以避免动态内存分配)和运算符重载
#include <cstdint>
#include <iostream>
template<class T, uint8_t ROWS, uint8_t COLUMNS>
class Matrix {
public:
T array[ROWS][COLUMNS];
Matrix<T, ROWS, COLUMNS> operator+(const Matrix<T, ROWS, COLUMNS> & m) const{
Matrix<T, ROWS, COLUMNS> result;
for(uint8_t row = 0; row < ROWS; row++){
for(uint8_t column = 0; column < COLUMNS; column++){
result.array[row][column] = array[row][column] + m.array[row][column];
}
}
return result;
}
Matrix<T, ROWS, COLUMNS> operator-(const Matrix<T, ROWS, COLUMNS> & m) const{
Matrix<T, ROWS, COLUMNS> result;
for(uint8_t row = 0; row < ROWS; row++){
for(uint8_t column = 0; column < COLUMNS; column++){
result.array[row][column] = array[row][column] - m.array[row][column];
}
}
return result;
}
template<uint8_t N>
Matrix<T, ROWS, N> operator*(const Matrix<T, COLUMNS, N>& m) const{
Matrix<T, ROWS, N> result;
for(uint8_t row = 0; row < ROWS; row++){
for(uint8_t column = 0; column < N; column++){
result.array[row][column] = 0;
for(uint8_t element = 0; element < COLUMNS; element++){
result.array[row][column] += array[row][element]*m.array[element][column];
}
}
}
return result;
}
friend Matrix<T, ROWS, COLUMNS> operator*(double k, const Matrix<T, ROWS, COLUMNS> & m){
Matrix<T, ROWS, COLUMNS> result;
for(uint8_t row = 0; row < ROWS; row++){
for(uint8_t column = 0; column < COLUMNS; column++){
result.array[row][column] = k*m.array[row][column];
}
}
return result;
}
friend Matrix<T, ROWS, COLUMNS> operator*(const Matrix<T, ROWS, COLUMNS> & m, double k){
Matrix<T, ROWS, COLUMNS> result;
for(uint8_t row = 0; row < ROWS; row++){
for(uint8_t column = 0; column < COLUMNS; column++){
result.array[row][column] = k*m.array[row][column];
}
}
return result;
}
void print(){
for(uint8_t row = 0; row < ROWS; row++){
for(uint8_t column = 0; column < COLUMNS; column++){
std::cout << "[" << (int)row << "]" << "[" << (int)column << "]: " << (double)array[row][column] << std::endl;
}
}
std::cout << std::endl;
}
};
我遇到过,每当我从重载的 *
运算符中删除 friend
修饰符以将矩阵乘以标量时,编译过程就会失败并显示以下错误消息:
Matrix.h:65:34:错误:'Matrix<T, ROWS, COLUMNS> Matrix<T, ROWS, COLUMNS>::operator*(double, const Matrix<T, ROWS, COLUMNS>&)' 必须有零个或一个参数
65 | Matrix 运算符*(double k, const Matrix & m){
Matrix.h:80:34:错误:'Matrix<T, ROWS, COLUMNS> Matrix<T, ROWS, COLUMNS>::operator*(const Matrix<T, ROWS, COLUMNS>&, double)' 必须有零个或一个参数
80 | Matrix 运算符*(const Matrix & m, double k){
谁能告诉我为什么需要 friend
修饰符?
对于二进制运算XXX
,如lhs XXX rhs
,
自由函数语法为 Ret operator XXX(const LHS&, const RHS&)
(当在class中定义时,应该是friend
)
对于LHS的成员方法,就是Ret LHS::operator XXX(RHS) const
(当在class内定义时,LHS::
应省略)
使用 friend
,您 declare/define 一个免费功能。没有,就是成员方法。
要处理 myDouble * myMatrix
,您需要免费功能 (friend Matrix operator*(double, const Matrix&)
)
要处理 myMatrix * myDouble
,您可以使用自由函数或方法。为了与上述情况对称,最好使用自由函数。 (所以 friend Matrix operator*(const Matrix&, double)
或 Matrix operator*(double) const
)。
我决定在学习C++期间将矩阵运算作为练习来实现。我选择了基于模板化 class 的方法(以避免动态内存分配)和运算符重载
#include <cstdint>
#include <iostream>
template<class T, uint8_t ROWS, uint8_t COLUMNS>
class Matrix {
public:
T array[ROWS][COLUMNS];
Matrix<T, ROWS, COLUMNS> operator+(const Matrix<T, ROWS, COLUMNS> & m) const{
Matrix<T, ROWS, COLUMNS> result;
for(uint8_t row = 0; row < ROWS; row++){
for(uint8_t column = 0; column < COLUMNS; column++){
result.array[row][column] = array[row][column] + m.array[row][column];
}
}
return result;
}
Matrix<T, ROWS, COLUMNS> operator-(const Matrix<T, ROWS, COLUMNS> & m) const{
Matrix<T, ROWS, COLUMNS> result;
for(uint8_t row = 0; row < ROWS; row++){
for(uint8_t column = 0; column < COLUMNS; column++){
result.array[row][column] = array[row][column] - m.array[row][column];
}
}
return result;
}
template<uint8_t N>
Matrix<T, ROWS, N> operator*(const Matrix<T, COLUMNS, N>& m) const{
Matrix<T, ROWS, N> result;
for(uint8_t row = 0; row < ROWS; row++){
for(uint8_t column = 0; column < N; column++){
result.array[row][column] = 0;
for(uint8_t element = 0; element < COLUMNS; element++){
result.array[row][column] += array[row][element]*m.array[element][column];
}
}
}
return result;
}
friend Matrix<T, ROWS, COLUMNS> operator*(double k, const Matrix<T, ROWS, COLUMNS> & m){
Matrix<T, ROWS, COLUMNS> result;
for(uint8_t row = 0; row < ROWS; row++){
for(uint8_t column = 0; column < COLUMNS; column++){
result.array[row][column] = k*m.array[row][column];
}
}
return result;
}
friend Matrix<T, ROWS, COLUMNS> operator*(const Matrix<T, ROWS, COLUMNS> & m, double k){
Matrix<T, ROWS, COLUMNS> result;
for(uint8_t row = 0; row < ROWS; row++){
for(uint8_t column = 0; column < COLUMNS; column++){
result.array[row][column] = k*m.array[row][column];
}
}
return result;
}
void print(){
for(uint8_t row = 0; row < ROWS; row++){
for(uint8_t column = 0; column < COLUMNS; column++){
std::cout << "[" << (int)row << "]" << "[" << (int)column << "]: " << (double)array[row][column] << std::endl;
}
}
std::cout << std::endl;
}
};
我遇到过,每当我从重载的 *
运算符中删除 friend
修饰符以将矩阵乘以标量时,编译过程就会失败并显示以下错误消息:
Matrix.h:65:34:错误:'Matrix<T, ROWS, COLUMNS> Matrix<T, ROWS, COLUMNS>::operator*(double, const Matrix<T, ROWS, COLUMNS>&)' 必须有零个或一个参数 65 | Matrix
运算符*(double k, const Matrix & m){ Matrix.h:80:34:错误:'Matrix<T, ROWS, COLUMNS> Matrix<T, ROWS, COLUMNS>::operator*(const Matrix<T, ROWS, COLUMNS>&, double)' 必须有零个或一个参数 80 | Matrix
运算符*(const Matrix & m, double k){
谁能告诉我为什么需要 friend
修饰符?
对于二进制运算XXX
,如lhs XXX rhs
,
自由函数语法为 Ret operator XXX(const LHS&, const RHS&)
(当在class中定义时,应该是friend
)
对于LHS的成员方法,就是Ret LHS::operator XXX(RHS) const
(当在class内定义时,LHS::
应省略)
使用 friend
,您 declare/define 一个免费功能。没有,就是成员方法。
要处理 myDouble * myMatrix
,您需要免费功能 (friend Matrix operator*(double, const Matrix&)
)
要处理 myMatrix * myDouble
,您可以使用自由函数或方法。为了与上述情况对称,最好使用自由函数。 (所以 friend Matrix operator*(const Matrix&, double)
或 Matrix operator*(double) const
)。