C++友元函数与类聚合问题:operator<<无法访问node类私有成员
问题原因
你当前遇到的访问权限错误核心是友元声明的匹配问题:
- 你在
node<T>类中声明的operator<<友元是与特定模板参数T绑定的非模板函数,而你将该运算符的实现写在tree_pos_vector<T>类内部时,模板实例化阶段编译器无法正确关联该实现与node<T>中声明的友元,因此不会授予该函数访问node<T>私有成员的权限。 - 额外的小问题:你当前的
operator<<实现没有返回std::ostream对象,不符合流运算符的定义规范,后续也会引发编译错误。
解决方法
方案1:调整友元声明为模板匹配模式
第一步,提前声明模板类和模板运算符:
template<class T> class tree_pos_vector; // 提前声明运算符模板 template<class T> std::ostream& operator<<(std::ostream &os, tree_pos_vector<T>& _tree);
第二步,修改node<T>类的友元声明,匹配模板运算符:
template<class T> class node{ private: int pos; int num_children; /* 其余成员省略 */ public: template<class W> friend class tree_pos_vector; // 声明实例化后的模板运算符为友元 friend std::ostream& operator<< <T>(std::ostream &os, tree_pos_vector<T>& _tree); };
第三步,将operator<<的实现挪到tree_pos_vector类外部:
template<class T> class tree_pos_vector{ private: std::vector<node<T>*> vec_node; /* 其余成员省略 */ public: // 声明模板运算符为友元 friend std::ostream& operator<< <T>(std::ostream &os, tree_pos_vector<T>& _tree); }; // 类外实现运算符 template<class T> std::ostream& operator<<(std::ostream &os, tree_pos_vector<T>& _tree){ for(auto &n: _tree.vec_node){ for(int i=0;i < n->num_children; i++){ os << "( "<< *n <<","<< _tree.vec_node[n->pos * degree + i] << ")\n"; } } return os; }
方案2:添加公共getter接口(更符合封装原则)
如果不想修改友元结构,可以直接在node<T>类中新增私有成员的访问接口,避免友元滥用:
template<class T> class node{ private: int pos; int num_children; /* 其余成员省略 */ public: // 新增getter接口 int get_pos() const { return pos; } int get_num_children() const { return num_children; } template<class W> friend class tree_pos_vector; friend std::ostream& operator<<(std::ostream &os,tree_pos_vector<T>& _tree); };
之后在operator<<中调用公共接口即可:
// 替换原来的访问逻辑 for(int i=0;i < n->get_num_children(); i++){ os << "( "<< *n <<","<< _tree.vec_node[n->get_pos() * degree + i] << ")\n"; }
内容的提问来源于stack exchange,提问作者flowibbia
相关产品推荐
相关产品推荐

