繁体   English   中英

关于在模板类中声明好友模板function的问题(C++)

[英]A question about declaring a friend template function in a template class(C++)

我正在写我的作业来实现矩阵的一些功能。 这是一个简化版本,以解决该问题。

#include <iostream>
using namespace std;

template<class T>
class CMyMatrix{
private:
    int row;
    int col;
    T** elements;
public:
    CMyMatrix(int row, int col);
    void SetMatrix(T* data, int row, int col);
    friend void DisplayMatrix(CMyMatrix<T> matrix);
};

template<class T>
CMyMatrix<T>::CMyMatrix(int row,int col) {
    this->row = row;
    this->col = col;
    this->elements = new T* [row];
    for (int i = 0;i < row;i++) {
        this->elements[i] = new T[col];
    }
}

template<class T>
void CMyMatrix<T>::SetMatrix(T* data, int row, int col) {
    this->row = row;
    this->col = col;
    if (elements != 0) delete[]elements;
    this->elements = new T* [row];
    for (int i = 0;i < row;i++) {
        this->elements[i] = new T[col];
    }
    for (int i = 0;i < row * col;i++) {
        elements[i / col][i % col] = data[i];
    }
}


template<class T>
void DisplayMatrix(CMyMatrix<T> matrix) {
    for (int i = 0;i < matrix.row;i++) {
        for (int j = 0;j < matrix.col;j++) {
            cout << matrix.elements[i][j] << " ";
            if (j == matrix.col - 1) {
                cout << endl;
            }
        }
    }
}

int main(){
    CMyMatrix<int> matrix(2, 3); 
    int a[6] = {1, 2, 3, 4, 5, 6};
    matrix.SetMatrix(a, 2, 3);
    DisplayMatrix(matrix);
    return 0;
}

我们的老师说我们必须将“DisplayMatrix”设为全局 function 所以它必须是 class CMyMatrix 的朋友 function(如果我不想写更多的函数)。 但也有这样的例外。
代码:LNK2019; 说明:在 function _main 中引用的未解析外部符号“void _cdecl DisplayMatrix(class CMyMatrix)”(?DisplayMatrix@@YAXV?$CMyMatrix@H@@@Z); 1号线; 文件:CMyMatrix.obj

我注意到 class CMyMatrix 中的“DisplayMatrix”在我的 IDE 中没有改变颜色,所以我认为可能存在一些问题。 但我不知道如何解决它。 如果有人可以帮助我,我将不胜感激。

friend元声明声明了一个非模板 function,它与全局 scope 中的 function 模板的定义不匹配。

你可以

// forward declaration
template<class T>
class CMyMatrix;

// declaration
template<class T>
void DisplayMatrix(CMyMatrix<T> matrix);

template<class T>
class CMyMatrix{
private:
    int row;
    int col;
    T** elements;
public:
    CMyMatrix(int row, int col);
    void SetMatrix(T* data, int row, int col);
    // friend declaration; refering to the function template
    friend void DisplayMatrix<T>(CMyMatrix<T> matrix);
    //                       ^^^
};

...

// definition
template<class T>
void DisplayMatrix(CMyMatrix<T> matrix) {
    for (int i = 0;i < matrix.row;i++) {
        for (int j = 0;j < matrix.col;j++) {
            cout << matrix.elements[i][j] << " ";
            if (j == matrix.col - 1) {
                cout << endl;
            }
        }
    }
}

或将模板friend声明为

template<class T>
class CMyMatrix{
private:
    int row;
    int col;
    T** elements;
public:
    CMyMatrix(int row, int col);
    void SetMatrix(T* data, int row, int col);
    // declares template friend;
    // note that all the instantiations of DisplayMatrix become friend
    template <class X>
    friend void DisplayMatrix(CMyMatrix<X> matrix);
};

...

template<class T>
void DisplayMatrix(CMyMatrix<T> matrix) {
    for (int i = 0;i < matrix.row;i++) {
        for (int j = 0;j < matrix.col;j++) {
            cout << matrix.elements[i][j] << " ";
            if (j == matrix.col - 1) {
                cout << endl;
            }
        }
    }
}

我想提出一个不是真正解决方案的答案。 这个非解决方案的重点是扩展解决方案的工作原理(我承认如果没有宋元瑶提供的答案,这个答案将毫无价值。)这可能有助于为未来的读者澄清事情,特别是如果某些评论消失了。

首先,这是一个简化的设置,其中我删除了一些与问题无关的内容(参见最小的、可重现的示例):

template<class T>
class CMyMatrix{
    friend void DisplayMatrix(CMyMatrix<T>);
};

template<class T>
void DisplayMatrix(CMyMatrix<T>) {
}

int main(){
    CMyMatrix<int> matrix;
    DisplayMatrix(matrix);
    return 0;
}

问题是friend被声明为(非模板)function,而DisplayMatrix的定义是function模板。 这些不匹配,因此编译器为标识符DisplayMatrix留下了两种含义。 当确定使用DisplayMatrix(matrix);行的含义时 ,编译器更喜欢非模板(已声明但从未定义)。

所以答案是让你的声明和定义一致。 做到这一点的一种方法——可能不是任何人都在寻找的解决方案,而是一种让编译器满意的方法——是将定义更改为不再是模板。

void DisplayMatrix(CMyMatrix<int>) {
}

通过此更改,代码可以编译。 好吧,只要您坚持使用int作为模板参数,它就符合要求。 所以不是真正的解决方案,而是friend声明实际声明的演示。 真正的解决方案是保留DisplayMatrix的(模板)定义并调整friend声明,如接受的答案所示。


有趣的是,gcc(但显然不是 clang?)有适用于这种情况的警告。

 warning: friend declaration 'void DisplayMatrix(CMyMatrix<T>)' declares a non-template function [-Wnon-template-friend] friend void DisplayMatrix(CMyMatrix<T> matrix); ^ note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM