繁体   English   中英

好友功能不允许访问私人成员

[英]Friend function not allowed to access private member

我认为友元函数可以访问所有成员。 即使在这个问题中它也有效:
C++友元函数不能访问私有成员

该问题中给出的答案似乎与我的代码相同,他的编译很好,而我的只是说 array_ 是私有的。 有谁知道为什么?

。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 ,并且numCols numRowsnumCols的声明中添加了const 那么有什么问题呢? 好...

你认为它是相同的,但你的代码有一个模板。 和朋友宣言

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);

不幸的是,由于这里解释的原因,这不起作用: 为什么模板只能在头文件中实现? 您将能够编译matrix.cpp ,但不能编译单独的驱动程序,如下所示:

#include <iostream>
#include "matrix.h"
using namespace std;
int main() {
    matrix<int> m;
    cout << m << endl;
}

您收到未定义的引用错误。 相反,您真的应该在标题中定义整个矩阵类并丢弃 .cpp 文件。

应该指出的是,这仍然有一个问题:你可以调用这个operator<<就好了,但是你不能,比如说,取它的地址,因为它只能通过参数相关的查找来找到。

auto ptr = static_cast<ostream&(*)(ostream&, const matrix<int>&)>(operator<<); // error

要通过非限定查找找到它,它必须在命名空间范围内具有匹配的声明。 而这样的声明其实是不可能写出来的(C++的语法是没有办法做到的)! 为了解决这个问题,我们需要将operator<<变成一个函数模板,定义为内联:

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);

现在上面取操作符地址的代码就可以工作了。

  1. 编译器抱怨是因为您实现的函数与您声明的函数不同(在声明中 rhs 被 const 修饰,在实现中它不是)。
  2. 在实现中添加 const 后,编译器会抱怨“未定义引用”,因为声明和实现仍然不一样。 实现是模板函数,声明不是。

     #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

暂无
暂无

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

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