友元函数访问类protected成员时报标识符未声明如何解决?
报错原因
- 直接触发未声明错误的原因:
list、length是arrayListType类的非静态protected成员,仅属于类的实例对象,全局作用域不存在这两个标识符。你在函数里直接裸写这两个名字,编译器只会在全局作用域查找匹配变量,找不到就会报未声明。所有类成员的访问,必须通过传入的类实例L做限定,不能脱离对象直接写。 - 会导致友元权限失效的隐藏问题:你在类内写的友元原型和实际定义的函数签名不匹配:一是原友元声明的第一个参数是值传递的
arrayListType <elemType>,和你函数定义里的引用传递参数类型不一致;二是模板类内部的裸友元声明,本质是为每个实例化的类单独声明一个非模板的普通函数,和你后续定义的全局模板incrementByConstant不属于同一个函数实体。就算你把成员访问的问题修好,也会因为权限不匹配报错。
修复步骤
- 添加前置声明
因为友元需要引用外部的模板类和模板函数,要在类定义的最前面加前置声明,让编译器提前识别这两个模板的存在:template <class elemType> class arrayListType; template <class elemType> void incrementByConstant(arrayListType<elemType>& L, int a); - 修正类内部的友元声明
把类里原来的友元声明改成和前置模板函数完全匹配的形式,在函数名后显式加上模板参数列表,告诉编译器这个友元是前面定义的模板函数的实例,不是新生成的独立普通函数:template <class elemType> class arrayListType { // 其他类内成员、方法 // 修正后的友元声明,<elemType>是关键匹配标识 friend void incrementByConstant<elemType>(arrayListType<elemType>& L, int a); protected: elemType * list; int length; int maxSize; // 其他类内成员、方法 }; - 修正函数定义里的成员访问逻辑
把原来裸写的成员标识符全部加上对象访问限定L.,明确告诉编译器你要访问的是传入实例的成员:template < class elemType > void incrementByConstant(arrayListType <elemType> &L, int a) { for(int i = 0; i < L.length; i++) { L.list[i] += a; } }
内容的提问来源于stack exchange,提问作者Ziyad
相关产品推荐
相关产品推荐

