[英]friend and template in C++
我的C ++代碼示例中存在一個大問題。 “朋友”和“模板”有問題。
錯誤消息:
Matrix.h:26:79:警告:
friend聲明'std :: ostream&matrixClass :: operator <<(std :: ostream&,const matrixClass :: Matrix&)'聲明一個非模板函數[-Wnon-template-friend] friend std :: ostream&operator <<(std :: ostream&,const Matrix&matrix);
Matrix.h:26:79:注意:
(if this is not what you intended, make sure the function template
已聲明並在此處添加<>后的函數名稱)
Matrix.h:28:77:警告:
friend declaration 'matrixClass::Matrix<T>*
matrixClass :: operator *(const matrixClass :: Matrix&,const matrixClass :: Matrix&)'聲明一個非模板函數[-Wnon-template-friend]朋友Matrix * operator *(const Matrix&m1,const Matrix&m2);
Matrix.cpp:1:0:
C:\\ Users \\ Peter \\ CLIONProjects \\ PK \\ untitled76 \\ Matrix.h:26:79:警告:朋友聲明'std :: ostream&matrixClass :: operator <<(std :: ostream&,const matrixClass :: Matrix&)'聲明非模板函數[-Wnon-template-friend]朋友std :: ostream&operator <<(std :: ostream&,const Matrix&matrix);
Matrix.h:26:79:注意:
(if this is not what you intended, make sure the function template
已聲明並在此處添加<>后的函數名稱)
Matrix.h:28:77:警告:
friend declaration 'matrixClass::Matrix<T>*
matrixClass :: operator *(const matrixClass :: Matrix&,const matrixClass :: Matrix&)'聲明一個非模板函數[-Wnon-template-friend]朋友Matrix * operator *(const Matrix&m1,const Matrix&m2);
CMakeFiles \\ untitled76.dir / objects.a(main.cpp.obj):在函數`main'中:
main.cpp:8:對main.cpp的未定義引用:8:對matrixClass::Matrix<int>::Matrix(int)'<br> main.cpp:10: undefined reference to
未定義引用matrixClass::Matrix<int>::Matrix(int)'<br> main.cpp:10: undefined reference to
matrixClass :: Matrix ::的matrixClass::Matrix<int>::Matrix(int)'<br> main.cpp:10: undefined reference to
set(int,int,int)'
main.cpp:11:對matrixClass::Matrix<int>::set(int, int, int)'<br> main.cpp:12: undefined reference to
未定義引用matrixClass::Matrix<int>::set(int, int, int)'<br> main.cpp:12: undefined reference to
matrixClass的matrixClass::Matrix<int>::set(int, int, int)'<br> main.cpp:12: undefined reference to
:: Matrix :: set(int,int ,int)'
main.cpp:13:對matrixClass::Matrix<int>::set(int, int, int)'<br> main.cpp:15: undefined reference to
未定義引用matrixClass::Matrix<int>::set(int, int, int)'<br> main.cpp:15: undefined reference to
matrixClass :: operator <<的matrixClass::Matrix<int>::set(int, int, int)'<br> main.cpp:15: undefined reference to
(std :: ostream& ,matrixClass :: Matrix const&)'
main.cpp:15:對matrixClass::operator<<(std::ostream&, matrixClass::Matrix<int> const&)'<br> main.cpp:8: undefined reference to
matrixClass :: Matrix ::〜的matrixClass::operator<<(std::ostream&, matrixClass::Matrix<int> const&)'<br> main.cpp:8: undefined reference to
矩陣()'
main.cpp:8:未定義引用`matrixClass :: Matrix :: ~Matrix()'
代碼: Matrix.h
#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
Matrix.cpp
#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;
}
main.cpp中
#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
聲明(作為非模板函數)內聯定義它:
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
聲明參考功能模板:
// 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;
}
}
關於未定義的引用錯誤,請參閱為什么模板只能在頭文件中實現?
這個答案使用朋友模板解決了非成員operator<<()
和operator*()
,這與使函數模板的實例成為朋友(由@songyuanyao提供的第二個解決方案)略有不同。 區別在於使用好友模板,模板函數的所有實例都是Matrix<>
類的朋友。 在這種情況下,我認為沒有任何實際差異,但在其他情況下,可能會有。 因此,無論如何,我想我會呈現它。
我想是這樣的。 兩個運算符都是非成員函數,這意味着它們獨立於Matrix<>
類,因此請獨立考慮它們的原型:
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);
現在,將T
替換為U
因為要使它們的所有實例成為Matrix<>
朋友,他們的原型需要包含在Matrix<>
的類定義中,它也是一個模板,並且它已經使用T
作為其模板參數。
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<>
朋友。 您只需要適當的語法:
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);
};
最后,它們都需要在matrixClass
namespace
,並且它們的聲明和定義需要按正確的順序排列,以便每個人都知道其他存在:
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*()
的原型以返回Matrix<U>
而不是Matrix<U>*
。 它的行為更像普通的operator*()
,它可以讓你做的事情如下: Matrix<int> m = m1*m2;
或m = m1*m2*m3;
。 此外,您的類的用戶不必擔心刪除operator*()
分配的內存或動態分配的性能成本。 只需在operator*()
創建一個局部Matrix<U>
變量並按值返回; 讓返回值優化(RVO)處理剩下的事情。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.