C ++中的朋友和模板

friend and template in C++

我的C++代码示例中有一个大问题。"friend"和"template"有问题。

错误消息:矩阵.h:26:79:警告:

friend declaration 'std::ostream&
matrixClass::operator<<(std::ostream&, const matrixClass::Matrix&)' declares a non-template function [-Wnon-template-friend] friend std::ostream &operator<<(std::ostream&, const Matrix &matrix);

矩阵H:26:79:注:

1
  (if this is not what you intended, make sure the function template

has already been declared and add <> after the function name here)

矩阵.h:28:77:警告:

1
  friend declaration 'matrixClass::Matrix<T>*

matrixClass::operator*(const matrixClass::Matrix&, const
matrixClass::Matrix&)' declares a non-template function
[-Wnon-template-friend]
friend Matrix* operator*(const Matrix &m1, const Matrix &m2);

CPP:1:0:

C:\Users\Peter\CLionProjects\PK\untitled76\Matrix.h:26:79: warning:
friend declaration 'std::ostream&
matrixClass::operator<<(std::ostream&, const matrixClass::Matrix&)' declares a non-template function [-Wnon-template-friend] friend std::ostream &operator<<(std::ostream&, const Matrix &matrix);

矩阵H:26:79:注:

1
  (if this is not what you intended, make sure the function template

has already been declared and add <> after the function name here)

矩阵.h:28:77:警告:

1
  friend declaration 'matrixClass::Matrix<T>*

matrixClass::operator*(const matrixClass::Matrix&, const
matrixClass::Matrix&)' declares a non-template function
[-Wnon-template-friend]
friend Matrix* operator*(const Matrix &m1, const Matrix &m2);

cmakefilesuntitled76.dir/objects.a(main.cpp.obj):在函数"main"中:

main.cpp:8:对的未定义引用main.cpp:8:未定义的对matrixClass::Matrix::Matrix(int)'
main.cpp:10: undefined reference to
matrixclass::matrix::set(int,int,int)'main.cpp:11:未定义的对matrixClass::Matrix::set(int, int, int)'
main.cpp:12: undefined reference to
matrixclass::matrix::set(int,int,int)'main.cpp:13:对matrixClass::Matrix::set(int, int, int)'
main.cpp:15: undefined reference to
matrixclass::operator<<(std::ostream&;,matrixclass::matrix const&;)的未定义引用'main.cpp:15:未定义对matrixClass::operator<<(std::ostream&, matrixClass::Matrix const&)'
main.cpp:8: undefined reference to
matrixclass::matrix::~matrix()的引用main.cpp:8:对"matrixclass::matrix::~matrix()"的未定义引用

代码:矩阵H

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#ifndef MATRIX_H_
#define MATRIX_H_

#include <iostream>

namespace matrixClass {

    template<class T>
    class Matrix {
    private:
        int dimension;
        T **m;
    public:
        Matrix(int d);

        Matrix(const Matrix &original);

        ~Matrix();

        void set(int x, int y, T value);

        T get(int x, int y) const;

        int getDimension() const;

        friend std::ostream &operator<<(std::ostream&, const Matrix<T> &matrix);

        friend Matrix<T>* operator*(const Matrix<T> &m1, const Matrix<T> &m2);
    };
}

#endif

矩阵式CPP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include"Matrix.h"

using namespace matrixClass;

template<class T>
Matrix<T>::Matrix(int d)
        : dimension{d}, m{new T *[d]} {
    //m = new T*[d];

    for (int i = 0; i < d; i++) {
        m[i] = new T[d];
    }
}

// COPY-CONSTRUCTOR
template<class T>
Matrix<T>::Matrix(const Matrix &original)
        : dimension{original.dimension},
          m{new T *[original.dimension]} {
    for (int i = 0; i < dimension; i++) {
        *(m + i) = *(original.m + i);
    }
}

// DESTRUCTOR
template<class T>
Matrix<T>::~Matrix() {
    for (int i = 0; i < dimension; i++) {
        delete[] m[i];
    }
    delete[] m;
}

template<class T>
void Matrix<T>::set(int x, int y, T value) {
    m[x][y] = value;
}

template<class T>
T Matrix<T>::get(int x, int y) const {
    return m[x][y];
}

template<class T>
int Matrix<T>::getDimension() const {
    return dimension;
}

template<class T>
std::ostream& operator<<(std::ostream& output, const Matrix<T>& matrix) {
    int dimension = matrix.getDimension();

    for(int x = 0; x < dimension; x++) {
        for(int y = 0; y < dimension; y++) {
            output << matrix.get(x, y) <<"";
        }
        return output;
    }
}

template<class T>
Matrix<T>* operator*(const Matrix<T>& m1, const Matrix<T>& m2) {
    int dimension = m1.getDimension();
    Matrix<T>* m = new Matrix<T>(dimension);

    for(int x = 0; x < dimension; x++) {
        for(int y = 0; y < dimension; y++) {
            T value = 0;
            for(int i = 0; i < dimension; i++) {
                value += m1.get(x, i) * m2.get(i, y);
            }
            m->set(x, y, value);
        }
    }
    return m;
}

主CPP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include"Matrix.h"

using namespace matrixClass;
using namespace std;

int main() {
    Matrix<int> m(2);

    m.set(0, 0, 1);
    m.set(0, 1, 2);
    m.set(1, 0, 3);
    m.set(1, 1, 4);

    cout << m <<"*" << endl << m <<"=" << endl;

    return 0;
}


friend宣言是一个operator<<非模板函数定义,而它说这是一个模板函数;他们不匹配。

你可以使用它内置的friend宣言(即非模板函数):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
template<class T>
class Matrix {
    ... ...
    friend std::ostream& operator<<(std::ostream& output, const Matrix<T>& matrix) {
        int dimension = matrix.getDimension();

        for(int x = 0; x < dimension; x++) {
            for(int y = 0; y < dimension; y++) {
                output << matrix.get(x, y) <<"";
            }
            return output;
        }
    }
    ... ...
};

或使friend指函数模板的声明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// class declaration
template<class T>
class Matrix;

// function declaration
template<class T>
std::ostream& operator<<(std::ostream& output, const Matrix<T>& matrix);

// class definition
template<class T>
class Matrix {
    ... ...
    friend std::ostream& operator<< <T>(std::ostream& output, const Matrix<T>& matrix);
    ... ...
};

// function definition
template<class T>
std::ostream& operator<<(std::ostream& output, const Matrix<T>& matrix) {
    int dimension = matrix.getDimension();

    for(int x = 0; x < dimension; x++) {
        for(int y = 0; y < dimension; y++) {
            output << matrix.get(x, y) <<"";
        }
        return output;
    }
}

关于未定义的错误和参考模板,实现CAN的湖泊为什么只在头文件?


这个问题的答案与你的地址和operator*()非会员朋友operator<<()使用不同的模板,这是略从制作实例函数模板(a Friend"解决方案由第二songyuanyao)。的差异是一个朋友的实例模板,模板函数都是一流的Matrix<>之友。在这个案例,我不认为有任何实际的差,但在其他有可能的。因此,我想我现在它无论如何。

我想它这样的。这两个非成员函数的算子是这意味着他们是独立Matrix<>酒店类的原型,所以想独立。

1
2
3
4
5
template<class T>
std::ostream& operator<<(std::ostream& output, const Matrix<T>& matrix);

template<class T>
Matrix<T>* operator*(const Matrix<T>& m1, const Matrix<T>& m2);

现在,因为有Ureplace T让所有人的朋友Matrix<>实例的原型,需要包含在类定义的模板,所以这是一Matrix<>,它已经使用T作为其模板参数。

1
2
3
4
5
template<class U>
std::ostream& operator<<(std::ostream& output, const Matrix<U>& matrix);

template<class U>
Matrix<U>* operator*(const Matrix<U>& m1, const Matrix<U>& m2);

现在,你可以让他们Matrix<>之友。所有你需要的是适当的语法:

1
2
3
4
5
6
7
8
9
10
template<class T>
class Matrix
{
    ...
    template<class U>
    friend std::ostream &operator<<(std::ostream&, const Matrix<U> &matrix);

    template<class U>
    friend Matrix<U>* operator*(const Matrix<U> &m1, const Matrix<U> &m2);
};

最后,他们都需要在matrixClassnamespace和他们的声明和定义,需要在正确的顺序,这样每个人都知道其他人的存在。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
namespace matrixClass {

// BEGIN Forward declarations

template<class T>
class Matrix;

template<class U>
std::ostream &operator<<(std::ostream&, const Matrix<U> &matrix);

template<class U>
Matrix<U>* operator*(const Matrix<U> &m1, const Matrix<U> &m2);

// END Forward declarations

template<class T>
class Matrix
{
    ...
    template<class U>
    friend std::ostream &operator<<(std::ostream&, const Matrix<U> &matrix);

    template<class U>
    friend Matrix<U>* operator*(const Matrix<U> &m1, const Matrix<U> &m2);
};

...

template<class U>
std::ostream& operator<<(std::ostream& output, const Matrix<U>& matrix)
{
    ...   // your implementation goes here
}

template<class U>
Matrix<U>* operator*(const Matrix<U>& m1, const Matrix<U>& m2)
{
    ...   // your implementation goes here
}

}   // end of namespace matrixClass

所有这些模板代码应该在头文件,它matrix.h,安切洛蒂已经被提到。

所以,我认为你应该改变operator*()to return Matrix原型Matrix*代替。它的行为像个正常operator*()想更多,它会使你做的事情:Matrix m = m1*m2;m = m1*m2*m3;样。此外,用户的等级不会有担心的代码分配的operator*()记忆性能或成本的动态配置。只是创建一个本地变量和Matrixoperator*()返回它的价值;让返回值优化(RVO)照顾的休息。