【问题标题】:Error happens when use friend function to manipulate private variables in template class in C++在 C++ 中使用友元函数操作模板类中的私有变量时发生错误
【发布时间】:2018-12-14 14:09:26
【问题描述】:

我最近在写一个矩阵运算库。我想在我的程序中重载operator,但是在我定义的模板类中使用友元函数访问私有变量时出错。 (而且只有当我重载操作符'+'时才报错,操作符'-'的重载函数不报错。) 我定义的模板类如下:

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。

【问题讨论】:

  • 问题是您使用类型变量将特定类型绑定到运算符重载,这没有意义,因为您使用的是类声明中的类型参数。看看here
  • 感谢您的回答。但是当我将它声明为类时,我没有将类型变量绑定到运算符。并且运算符'-'的重载可以单独正确运行。你能给我一些关于如何纠正它的建议吗?
  • 请注意,vc6 受到难以置信的限制,尤其是在 c++ 模板方面。即使是介绍性工作,切换到更新的编译器也会为您提供很好的服务。a

标签: c++ class templates friend


【解决方案1】:

friend Matrix operator+(const Matrix &amp;a, const Matrix &amp;b); 不是模板。它是模板类的非模板友元函数。

template&lt;class T&gt;Matrix&lt;T&gt; operator +(const Matrix&lt;T&gt; &amp;m1, const Matrix&lt;T&gt; &amp;m2) 是一个模板。它们不是同一个功能,因为一个是模板,另一个不是。

解决此问题的最简单方法是将正文内联放入模板类定义中。

第二种最简单的方法是从operator+ 转发到某个静态方法或某个命名函数模板。在模板类定义前前向声明,在模板类定义中为友,事后实现。

(您实际上希望operator+ 成为模板类的非模板朋友,因为这样可以更好地处理转换。)

https://stackoverflow.com/a/13464246/1774667 也是如此,但对于命名函数,而不是运算符。叫它add

然后是friend Matrix operator+(const Matrix &amp;a, const Matrix &amp;b){ return add(a,b); },它为您提供了模板类魔术的非模板友元运算符。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-31
    • 2017-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-20
    相关资源
    最近更新 更多