如何通过友元声明让类B访问类A的私有模板别名?
解决类B访问类A私有模板别名的问题
这个问题的核心是友元关系搞反了——你现在是在B里把A声明为友元,但我们需要的是A主动授权B访问它的私有成员,毕竟私有成员的访问权限是由拥有者(A)说了算的。另外因为两个都是模板类,友元声明的模板参数匹配也要注意。
错误原因分析
你原来的代码里,A的V是私有模板别名,B想要访问它,但友元声明写在了B里面:friend Prev;,这其实是让A成为B的友元,完全搞反了权限方向。正确的做法是在A内部声明B是它的友元,这样B才有资格访问A的私有成员。
修正后的通用代码
#include <iostream> #include <vector> // 先前置声明B模板,因为A里要引用它 template <typename T, class Prev> class B; template <class T> class A { private: template<typename R> using V = std::vector<R>; // 声明所有B的模板实例为友元,这样任意B实例都能访问A的私有成员 template<typename U, class P> friend class B; }; template <typename T, class Prev> class B { public: // 注意这里的typename和template关键字:因为V是依赖于Prev的模板,必须用template标识 typename Prev::template V<T> v_; }; int main() { B<int, A<int>> b; return 0; }
更精确的友元声明(可选)
如果你不想让所有B的实例都能访问A的私有成员,可以缩小友元范围:
只允许第二个参数为当前
A<T>的B实例访问:
在A的私有部分改成:friend class B<T, A<T>>;这样只有
B<int, A<int>>能访问A<int>的V,B<double, A<int>>就无法访问。允许所有以
A<T>为第二个参数的B实例访问:
在A的私有部分改成:template<typename U> friend class B<U, A<T>>;这样
B<int, A<int>>、B<double, A<int>>这类实例都能访问A<int>的私有成员。
额外注意点
在B中访问Prev::template V<T>时,必须加template关键字——因为V是依赖于模板参数Prev的模板,编译器需要你明确告诉它这是一个模板,否则会把V当成普通成员变量解析,导致编译错误。
内容的提问来源于stack exchange,提问作者R zu
相关产品推荐
相关产品推荐

