C++正确定义的友元函数调用时提示未声明/未定义引用如何解决?
问题成因
C++中,类内部的友元声明仅用于授予该函数访问类私有/保护成员的权限,不会将该函数的声明注入到类的外层作用域,普通名字查找无法直接找到这类友元函数,只有参数依赖查找(ADL)可以在函数参数关联的类作用域中找到友元声明。
你遇到的报错原因刚好对应这个规则:
generate函数的参数是size_t(内置类型,无关联类作用域),ADL无法触发,编译器在main函数所在的全局作用域找不到generate的声明,因此抛出未定义错误。- 你额外在main.cpp声明
generate后能正常运行,就是因为补全了全局作用域的函数声明,让编译器能找到该函数的定义。 - 同是友元的
operator<<没有报错,是因为它的第二个参数是Random类对象,ADL会自动在Random的类作用域查找函数,因此能匹配到类内部的友元声明。
解决方案
最优的解决方案是在Random.h头文件的类定义外部,补充generate函数的全局声明,这样所有引入该头文件的编译单元都能直接使用该函数,无需单独重复声明:
修改后的Random.h代码:
// Random Declarations #ifndef _RANDOM_H #define _RANDOM_H #include <stdint.h> #include <vector> #include <ostream> using uv = std::vector<uint16_t>; using std::ostream; using std::size_t; class Random { uv data; public: friend Random generate(const size_t&); friend ostream& operator<< (ostream&, const Random&); }; // 补充全局作用域的generate函数声明 Random generate(const size_t&); #endif
其他可选方案(按需选择):
- 将
generate改为Random类的静态成员函数,直接通过Random::generate(10U)调用,无需友元声明即可访问类私有成员。 - 若项目使用自定义命名空间包裹
Random类,将generate也放入同一命名空间,调用时指定命名空间即可。
内容的提问来源于stack exchange,提问作者Sp Maurya
相关产品推荐
相关产品推荐

