为什么需要使用 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 修饰符以将矩阵乘以标量时,编译过程就会失败并显示以下错误消息:

谁能告诉我为什么需要 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)。