Ошибка происходит, когда используется функция Friend для управления закрытыми переменными в шаблонном классе в C ++ - PullRequest
0 голосов
/ 06 июля 2018

Недавно я пишу библиотеку матричных операций. И я хочу перегрузить операторы s в моей программе, но ошибка произошла, когда я использую функцию Friend для доступа к закрытым переменным в классе шаблона, который я определил. (И он сообщает об ошибке только тогда, когда я перегружаю оператор '+', а функция перегрузки операции '-' не сообщает об ошибке.) класс шаблона, который я определил ниже:

template<class T>
class Matrix
{
    int col;
    int row;
    T *matrix;
    public:
        Matrix(T *m, int row1, int col1):matrix(m), row(row1), col(col1){}
        Matrix(int row1, int col1):row(row1), col(col1)
        {
            matrix = new T[row*col];
            cout<<"Have set the shape of the matrix, but should use create() to initialize the matrix!"<<endl;
        }
        Matrix(){}
        ~Matrix(){}
        void show();
        UINT create(T *m);
        UINT zeros(int size);
        UINT eye(int size);

        // the overload function statement
        friend Matrix operator+(const Matrix &a, const Matrix &b);
        friend Matrix operator-(const Matrix &a, const Matrix &b);

        Matrix matrix_T();              // transpose the matrix
        Matrix matrix_Inv();            // calculate matrix's inverse
        Matrix matrix_Adjoint();        // calculate the adjoint matrix
};

И определение этих двух функций перегрузки приведено ниже:

// report error: can't access private member declared in class
template<class T>
Matrix<T> operator +(const Matrix<T> &m1, const Matrix<T> &m2)
{
    if (m1.col!=m2.col || m1.row!=m2.row)
    {
        cout<<"These two matrices can't be plused!"<<endl;
        exit(0);
    }
    T *tmp = new T[m1.col*m1.row];
    for (int i=0; i<m1.row; i++)
    {
        for (int j=0; j<m1.col; j++)
        {
            tmp[i*m1.col+j] = m1.matrix[i*m1.col+j] + m2.matrix[i*m1.col+j];
        }
    }
    return Matrix<T>(tmp, m1.row, m1.col);
}


// this defination didn't report error
// and if I only run this code, there is nothing wrong
template<class T>
Matrix<T> operator -(const Matrix<T> &m1, const Matrix<T> &m2)
{
    if (m1.col!=m2.col || m1.row!=m2.row)
    {
        cout<<"These two matrices can't be plused!"<<endl;
        exit(0);
    }
    T *tmp = new T[m1.col*m1.row];
    for (int i=0; i<m1.row; i++)
    {
        for (int j=0; j<m1.col; j++)
        {
            tmp[i*m1.col+j] = m1.matrix[i*m1.col+j] - m2.matrix[i*m1.col+j];
        }
    }
    return Matrix<T>(tmp, m1.row, m1.col);
}

Я тестировал эти два фрагмента кода отдельно, перегрузка оператора «-» может быть скомпилирована правильно, а оператор «+» - нет. Информация об ошибках ниже:

f:\program\c++\matrixoperate\matrixdefine.h(134) : error C2248: 'col' : cannot access private member declared in class 'Matrix<int>'
    f:\program\c++\matrixoperate\matrixdefine.h(6) : see declaration of 'col'
    f:\program\c++\matrixoperate\demo.cpp(14) : see reference to function template instantiation 'class Matrix<int> __cdecl operator +(const class Matrix<int> &,const class Matrix<int> &)' being compiled
f:\program\c++\matrixoperate\matrixdefine.h(134) : error C2248: 'col' : cannot access private member declared in class 'Matrix<int>'
    f:\program\c++\matrixoperate\matrixdefine.h(6) : see declaration of 'col'

И IDE, которую я использую, это VC ++ 6.0.

1 Ответ

0 голосов
/ 06 июля 2018

friend Matrix operator+(const Matrix &a, const Matrix &b); не шаблон. Это не шаблонная функция друга шаблонного класса.

template<class T>Matrix<T> operator +(const Matrix<T> &m1, const Matrix<T> &m2) это шаблон. Они не являются одной и той же функцией, поскольку один является шаблоном, а другой - нет.

Самый простой способ исправить это - поместить тело в строку в определении класса шаблона.

Второй самый простой способ - перейти от operator+ к статическому методу или шаблону именованной функции. Форвард объявить его до определения класса шаблона, добавить его в определение класса шаблона, реализовать его после войны.

(Вы на самом деле хотите, чтобы operator+ был другом, не являющимся шаблоном шаблона класса, так как это делает его намного лучше с конверсиями.)

То же самое делают https://stackoverflow.com/a/13464246/1774667, но для именованной функции, а не для оператора. Назовите это add.

Тогда friend Matrix operator+(const Matrix &a, const Matrix &b){ return add(a,b); }, который дает вам не шаблонный оператор друга класса шаблона magic.

...