好友功能不允许访问私有成员
Friend function not allowed to access private member
我以为友元函数可以访问所有成员。即使在这个问题上它也有效:
C++ friend function can't access private members
那个问题给出的答案似乎与我的代码相同,而且他的编译很好,而我的只是说 array_ 是 pivate。有人知道为什么吗?
.h:
#ifndef matrix_h
#define matrix_h
#include <iostream>
using namespace std;
template <typename Comparable>
class matrix
{
private:
size_t num_cols_;
size_t num_rows_;
Comparable **array_;
public:
friend ostream& operator<< (ostream& o, const matrix<Comparable> & rhs);
size_t NumRows();
size_t NumCols();
};
#endif
.cpp:
#include <iostream>
#include "matrix.h"
using namespace std;
template <typename Comparable>
ostream& operator<< (ostream& o, matrix<Comparable> & rhs){
size_t c = rhs.NumRows();
size_t d = rhs.NumCols();
for (int i = 0; i < c; i++){
for (int j = 0; j < d; j++){
o << rhs.array_[i][j]; //not allowed
}
o << endl;
}
return o;
}
template <typename Comparable>
size_t matrix<Comparable>::NumRows(){
return num_rows_;
}
template <typename Comparable>
size_t matrix<Comparable>::NumCols(){
return num_cols_;
}
int main(){
matrix<int> a;
cout << a << endl;
}
假设您在两个地方都使用了 const
,并将 const
添加到 numRows
和 numCols
的声明中。那有什么问题呢?嗯...
你认为它是相同的,但你的代码有一个模板。和朋友声明
friend ostream& operator<< (ostream& o, const matrix<Comparable> & rhs);
不是模板,所以不符合定义
template <typename Comparable>
ostream& operator<< (ostream& o, matrix<Comparable> & rhs){ // ...
其中是一个模板。事实上gcc会给出一个警告:
matrix.h:16:79: warning: friend declaration ‘std::ostream& operator<<(std::ostream&, const matrix<Comparable>&)’ declares a non-template function [-Wnon-template-friend]
friend ostream& operator<< (ostream& o, const matrix<Comparable> & rhs);
^
matrix.h:16:79: note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here)
把所有的专业都当朋友是很有诱惑力的,就像这样:
template <typename T>
friend ostream& operator<< (ostream& o, const matrix<T> & rhs);
不幸的是,由于此处解释的原因,这将不起作用:Why can templates only be implemented in the header file? 您将能够编译 matrix.cpp
,但不能编译单独的 driver 程序,如下所示:
#include <iostream>
#include "matrix.h"
using namespace std;
int main() {
matrix<int> m;
cout << m << endl;
}
您收到未定义的引用错误。相反,您真的应该在 header 中定义整个矩阵 class 并放弃 .cpp 文件。
需要指出的是,这还有一个问题:你可以调用这个operator<<
就好了,但是你不能,比如说,取它的地址,因为它只能通过argument-dependent查找。
auto ptr = static_cast<ostream&(*)(ostream&, const matrix<int>&)>(operator<<); // error
要通过非限定查找找到它,它必须在命名空间范围内具有匹配的声明。而且这样的声明实际上是不可能写的(C++的语法根本没有办法做到)!为了解决这个问题,我们需要将 operator<<
变成一个函数模板,定义为 inline:
template <typename Comparable>
class matrix {
// ...
template <typename T>
friend ostream& operator<<(ostream& o, const matrix<T>& rhs) {
// ...
}
// ...
};
// namespace-scope declaration
template <typename T>
ostream& operator<<(ostream& o, const matrix<T>& rhs);
现在上面获取操作员地址的代码可以工作了。
- 编译器报错是因为你实现的函数与你声明的不同(在声明中 rhs 被 const 装饰,在实现中它不是)。
在实现中添加 const 后,编译器会报错 "Undefined reference" 因为声明和实现仍然不一样。实现是模板函数,声明不是。
#ifndef matrix_h
#define matrix_h
#include <iostream>
using namespace std;
template <typename Comparable>
class matrix
{
private:
size_t num_cols_;
size_t num_rows_;
Comparable **array_;
public:
template<typename T>
friend ostream& operator<< (ostream& o, const matrix<T> & rhs);
size_t NumRows() const;
size_t NumCols() const;
};
template <typename Comparable>
ostream& operator<< (ostream& o, const matrix<Comparable> & rhs){
size_t c = rhs.NumRows();
size_t d = rhs.NumCols();
for (int i = 0; i < c; i++){
for (int j = 0; j < d; j++){
o << rhs.array_[i][j]; //not allowed
}
o << endl;
}
return o;
}
template <typename Comparable>
size_t matrix<Comparable>::NumRows() const{
return num_rows_;
}
template <typename Comparable>
size_t matrix<Comparable>::NumCols() const{
return num_cols_;
}
#endif
我以为友元函数可以访问所有成员。即使在这个问题上它也有效:
C++ friend function can't access private members
那个问题给出的答案似乎与我的代码相同,而且他的编译很好,而我的只是说 array_ 是 pivate。有人知道为什么吗?
.h:
#ifndef matrix_h
#define matrix_h
#include <iostream>
using namespace std;
template <typename Comparable>
class matrix
{
private:
size_t num_cols_;
size_t num_rows_;
Comparable **array_;
public:
friend ostream& operator<< (ostream& o, const matrix<Comparable> & rhs);
size_t NumRows();
size_t NumCols();
};
#endif
.cpp:
#include <iostream>
#include "matrix.h"
using namespace std;
template <typename Comparable>
ostream& operator<< (ostream& o, matrix<Comparable> & rhs){
size_t c = rhs.NumRows();
size_t d = rhs.NumCols();
for (int i = 0; i < c; i++){
for (int j = 0; j < d; j++){
o << rhs.array_[i][j]; //not allowed
}
o << endl;
}
return o;
}
template <typename Comparable>
size_t matrix<Comparable>::NumRows(){
return num_rows_;
}
template <typename Comparable>
size_t matrix<Comparable>::NumCols(){
return num_cols_;
}
int main(){
matrix<int> a;
cout << a << endl;
}
假设您在两个地方都使用了 const
,并将 const
添加到 numRows
和 numCols
的声明中。那有什么问题呢?嗯...
你认为它是相同的,但你的代码有一个模板。和朋友声明
friend ostream& operator<< (ostream& o, const matrix<Comparable> & rhs);
不是模板,所以不符合定义
template <typename Comparable>
ostream& operator<< (ostream& o, matrix<Comparable> & rhs){ // ...
其中是一个模板。事实上gcc会给出一个警告:
matrix.h:16:79: warning: friend declaration ‘std::ostream& operator<<(std::ostream&, const matrix<Comparable>&)’ declares a non-template function [-Wnon-template-friend]
friend ostream& operator<< (ostream& o, const matrix<Comparable> & rhs);
^
matrix.h:16:79: note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here)
把所有的专业都当朋友是很有诱惑力的,就像这样:
template <typename T>
friend ostream& operator<< (ostream& o, const matrix<T> & rhs);
不幸的是,由于此处解释的原因,这将不起作用:Why can templates only be implemented in the header file? 您将能够编译 matrix.cpp
,但不能编译单独的 driver 程序,如下所示:
#include <iostream>
#include "matrix.h"
using namespace std;
int main() {
matrix<int> m;
cout << m << endl;
}
您收到未定义的引用错误。相反,您真的应该在 header 中定义整个矩阵 class 并放弃 .cpp 文件。
需要指出的是,这还有一个问题:你可以调用这个operator<<
就好了,但是你不能,比如说,取它的地址,因为它只能通过argument-dependent查找。
auto ptr = static_cast<ostream&(*)(ostream&, const matrix<int>&)>(operator<<); // error
要通过非限定查找找到它,它必须在命名空间范围内具有匹配的声明。而且这样的声明实际上是不可能写的(C++的语法根本没有办法做到)!为了解决这个问题,我们需要将 operator<<
变成一个函数模板,定义为 inline:
template <typename Comparable>
class matrix {
// ...
template <typename T>
friend ostream& operator<<(ostream& o, const matrix<T>& rhs) {
// ...
}
// ...
};
// namespace-scope declaration
template <typename T>
ostream& operator<<(ostream& o, const matrix<T>& rhs);
现在上面获取操作员地址的代码可以工作了。
- 编译器报错是因为你实现的函数与你声明的不同(在声明中 rhs 被 const 装饰,在实现中它不是)。
在实现中添加 const 后,编译器会报错 "Undefined reference" 因为声明和实现仍然不一样。实现是模板函数,声明不是。
#ifndef matrix_h #define matrix_h #include <iostream> using namespace std; template <typename Comparable> class matrix { private: size_t num_cols_; size_t num_rows_; Comparable **array_; public: template<typename T> friend ostream& operator<< (ostream& o, const matrix<T> & rhs); size_t NumRows() const; size_t NumCols() const; }; template <typename Comparable> ostream& operator<< (ostream& o, const matrix<Comparable> & rhs){ size_t c = rhs.NumRows(); size_t d = rhs.NumCols(); for (int i = 0; i < c; i++){ for (int j = 0; j < d; j++){ o << rhs.array_[i][j]; //not allowed } o << endl; } return o; } template <typename Comparable> size_t matrix<Comparable>::NumRows() const{ return num_rows_; } template <typename Comparable> size_t matrix<Comparable>::NumCols() const{ return num_cols_; } #endif