【问题标题】:How to enable a friend class's friend function access its private members directly in C++如何启用朋友类的朋友函数直接在 C++ 中访问其私有成员
【发布时间】:2020-05-24 08:09:23
【问题描述】:

我正在写一个稀疏矩阵类,我想通过重载operator<<来输出稀疏矩阵。 我想知道如何启用 SMatrix (operator<<) 的好友功能直接(不是通过某些接口) 访问 TriTuple 的私有数据成员?请注意,SMatrix 同时是 TriTuple 的朋友类。见代码如下。

// tri-tuple term for sparse matrix by the form <row, col, value>
template<typename T>
class TriTuple {
    template<typename U> friend class SMatrix;
    // enable friend of SMatrix access private members of TriTuple
    // declaring like this? feasible in VS2019, but not in gcc
    template<typename U>
    friend std::ostream& operator<<(std::ostream& os, const SMatrix<U>& M);
private:
    size_t _row, _col;
    T _val;
public:
    //...
};

// sparse matrix
template<typename T>
class SMatrix {
    template<typename U>
    friend std::ostream& operator<<(std::ostream& os, const SMatrix<U>& M);
private:
    size_t _rows, _cols;// # of rows & columns
    size_t _terms;      // # of terms
    TriTuple<T>* _arr;  // stored by 1-dimensional array
    size_t _maxSize;
public:
    //...  
};

template<typename U>
std::ostream& operator<<(std::ostream& os, const SMatrix<U>& M)
{
    M.printHeader();
    for (size_t i = 0; i < M._terms; ++i) {
        os << M._arr[i]._row << "\t\t" << M._arr[i]._col << "\t\t" << M._arr[i]._val << '\n';
    }
    return os;
}

在VS2019(可能是C++17)可以成功编译运行,但是在gcc中编译失败(目前只有c++11可用)。 那是c ++标准版的问题吗? (它指的是“ISO C++ 禁止声明......”)我应该如何改进声明? 请参阅下图中的错误消息。 gcc error_msg 提前谢谢你们了不起的家伙:-)

【问题讨论】:

  • 经过多年的 c++ 和 python,我明白 private 只对保护类的不变量有意义。我会简单地删除 private 和 friend,使用关键字 struct 而不是 class 并访问我需要的值。
  • 注意:GCC 在最近的版本中支持 C++17。编译时只需传递-std=c++17 选项即可。

标签: c++ templates sparse-matrix ostream friend-function


【解决方案1】:

[class.friend]/p11:

如果友元声明出现在本地类 ([class.local]) 中并且指定的名称是非限定名称,则在不考虑最内层非类范围之外的范围的情况下查找先前的声明。对于友元函数声明,如果没有事先声明,则程序是非良构的。对于友元类声明,如果没有前面的声明,则指定的类属于最内层的非类范围,但如果随后被引用,则在匹配的声明之前无法通过名称查找找到其名称在最内层的非类范围内提供。

您需要提供SMatrix 的定义,或者至少在引用它之前对其进行前向声明:

template <typename U>
class SMatrix;

【讨论】:

    【解决方案2】:

    此错误与 SMatrix 类的前向声明有关。 只是尝试转发声明

    template<typename T>
    class SMatrix;
    

    TriTuple上方。

    查看godbolt

    operator&lt;&lt; 中也没有检查空矩阵。我建议你使用-fsanitize=undefined -fsanitize=address 来支持 gcc。

    【讨论】:

    • 感谢您的建设性意见
    猜你喜欢
    • 2021-08-16
    • 1970-01-01
    • 2015-11-24
    • 1970-01-01
    • 2015-03-06
    • 1970-01-01
    • 2021-11-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多