如何用GMock的MOCK_METHOD模拟返回引用的重载类型转换运算符?
模拟返回引用的类型转换运算符时的编译错误分析与修复
问题场景
你有一个重载了返回引用类型的类型转换运算符的类,示例如下:
class MyClass : public MyClassInterface { public: virtual ~MyClass() override; operator const int&() const override { return m_value; } private: int m_value{}; };
可以通过int val = myclass;的方式获取值。
你参考了以下可正常编译的gmock模拟示例:
class Foo { public: virtual ~Foo() {} virtual int operator[](int index) = 0; }; class MockFoo : public Foo { public: MOCK_METHOD(int, BracketOp, (int index)); virtual int operator[](int index) override { return BracketOp(index); } };
但适配自己的需求时写出了如下代码,出现编译错误:
class Bar { public: virtual ~Bar() {} virtual operator const int&() = 0; }; class MockBar : public Bar { public: MOCK_METHOD(int, RefOp, ()); virtual operator const int&() override { return RefOp(); } };
错误信息
error: returning reference to temporary [-Werror=return-local-addr] 1173 | virtual operator const int&() override { return RefOp(); } | ~~~~~^~
错误原因
RefOp()被声明为返回值类型int,当你在类型转换运算符中返回它的结果时,会生成一个临时int对象。而类型转换运算符要求返回const int&引用,引用绑定到这个临时对象后,临时对象会在当前语句结束后立即销毁,导致引用变成悬空引用,这就是编译器抛出错误的核心原因。- 对比
MockFoo的情况:operator[]和BracketOp都返回值类型int,直接返回值不存在引用绑定临时对象的问题,因此可以正常编译。
修复方案
需要让模拟方法RefOp()的返回类型与纯虚运算符的返回类型一致,即返回const int&,同时要确保引用指向的对象具有足够长的生命周期(比如Mock类内部持有成员变量,或通过gmock动作返回对外部持久对象的引用)。
修改后的正确代码
class Bar { public: virtual ~Bar() {} virtual operator const int&() = 0; }; class MockBar : public Bar { public: // 将RefOp的返回类型改为const int&,匹配运算符的返回类型 MOCK_METHOD(const int&, RefOp, ()); virtual operator const int&() override { return RefOp(); } private: // 可选:如果需要模拟固定值,可持有一个成员变量供引用返回 int m_mock_value{}; };
使用示例
通过gmock的ReturnRef动作指定返回的引用对象,确保对象生命周期足够:
MockBar mock_bar; int test_val = 42; // 指定RefOp返回test_val的引用 EXPECT_CALL(mock_bar, RefOp()) .WillRepeatedly(ReturnRef(test_val)); // 使用类型转换 const int& val_ref = mock_bar; int val = mock_bar;
内容的提问来源于stack exchange,提问作者Ingo
相关产品推荐
相关产品推荐

