重载operator<<时无法访问类私有成员,命名空间语法是否正确?
问题:重载operator<<时触发C2248私有成员访问错误
在MS Visual Studio 2019中重载operator<<时,出现C2248错误,无法访问Instruction::Device_Impedance类的私有成员m_minimum_ohms和m_maximum_ohms,询问operator<<的实现是否存在命名空间语法错误。
错误信息
Severity Code Description Project File Line Suppression State Error C2248 'Instruction::Device_Impedance::m_minimum_ohms': cannot access private member declared in class 'Instruction::Device_Impedance' friend_ostream_namespace device_impedance.cpp 13 Severity Code Description Project File Line Suppression State Error C2248 'Instruction::Device_Impedance::m_maximum_ohms': cannot access private member declared in class 'Instruction::Device_Impedance' friend_ostream_namespace device_impedance.cpp 14
相关代码文件
device_impedance.hpp
#ifndef INSTRUCTION_DEVICE_IMPEDANCE_HPP #define INSTRUCTION_DEVICE_IMPEDANCE_HPP #include <string> #include <iostream> namespace Instruction { class Device_Impedance { public: Device_Impedance(); Device_Impedance(const unsigned int min_ohms, const unsigned int max_ohms); //! Constructor -- Copy Device_Impedance(const Device_Impedance& di); //! Destructor ~Device_Impedance(); public: Device_Impedance& operator=(const Device_Impedance& di); friend std::ostream& operator<< (std::ostream& out, const Instruction::Device_Impedance& di); //-------------------------------------------------------------------------- // Public Methods //-------------------------------------------------------------------------- public: const std::string& get_name() const override; //-------------------------------------------------------------------------- // Private Members //-------------------------------------------------------------------------- private: unsigned int m_minimum_ohms; unsigned int m_maximum_ohms; }; } // End namespace Instruction /*! @} // End Doxygen Group */ #endif // INSTRUCTION_DEVICE_IMPEDANCE_HPP
device_impedance.cpp
#include "device_impedance.hpp" using namespace Instruction; /*! * \details Output the instruction name to the stream. */ std::ostream& operator<< (std::ostream& out, const Instruction::Device_Impedance& di) { out << di.get_name() //***** The next two lines are causing the error. << " " << di.m_minimum_ohms << ", " << di.m_maximum_ohms << "\n"; return out; } const std::string& Device_Impedance :: get_name() const { static std::string instruction_name{"DEVICE_IMPEDANCE"}; return instruction_name; }
问题原因与解决方案
问题核心是友元函数的命名空间不匹配:
头文件中,Device_Impedance类声明的友元operator<<是全局命名空间的函数,但cpp文件中实现的operator<<虽然用了using namespace Instruction;,但函数本身仍属于全局命名空间。编译器会认为这是两个完全不同的函数——头文件里的全局友元函数,和cpp里的全局普通函数,因此cpp中的函数没有访问私有成员的权限,触发C2248错误。
解决方案1:将operator<<实现放入Instruction命名空间
修改cpp文件,把operator<<的定义包裹在Instruction命名空间块内,确保和类的归属一致:
#include "device_impedance.hpp" namespace Instruction { std::ostream& operator<< (std::ostream& out, const Device_Impedance& di) { out << di.get_name() << " " << di.m_minimum_ohms << ", " << di.m_maximum_ohms << "\n"; return out; } } // End namespace Instruction const std::string& Instruction::Device_Impedance::get_name() const { static std::string instruction_name{"DEVICE_IMPEDANCE"}; return instruction_name; }
解决方案2:调整头文件友元声明,指定命名空间
先在Instruction命名空间内提前声明该函数,再在类中明确友元归属:
#ifndef INSTRUCTION_DEVICE_IMPEDANCE_HPP #define INSTRUCTION_DEVICE_IMPEDANCE_HPP #include <string> #include <iostream> namespace Instruction { // 提前声明类和友元函数 class Device_Impedance; std::ostream& operator<< (std::ostream& out, const Device_Impedance& di); class Device_Impedance { public: // ... 其他成员保持不变 ... // 声明当前命名空间的函数为友元 friend std::ostream& operator<< (std::ostream& out, const Device_Impedance& di); // ... 其他成员保持不变 ... }; } // End namespace Instruction #endif // INSTRUCTION_DEVICE_IMPEDANCE_HPP
两种方案中,第一种更简洁直观,符合常规的命名空间使用习惯,优先推荐。
内容的提问来源于stack exchange,提问作者Thomas Matthews
相关产品推荐
相关产品推荐

