如何让成员函数返回指向const类型的std::unique_ptr引用?
问题解答
首先直接给结论:没办法直接让getFoo()返回std::unique_ptr<const Foo>&。原因很简单——std::unique_ptr<Foo>和std::unique_ptr<const Foo>是完全独立的类型,不存在隐式的引用转换关系,你没法把前者的引用直接转换成后者的引用。
不过你的核心需求(用户只能读Foo、只能通过set_number修改状态)是完全可以实现的,下面给几个实用的方案:
方案1:返回const Foo*(最直接的替代)
虽然用到了get(),但这是最贴合你“原始指针用法”需求的方案,而且完全符合权限控制:
class ManageFoo { private: std::unique_ptr<Foo> foo_ptr; public: // 返回指向const Foo的原始指针,用户只能调用Foo的const成员 const Foo* getFoo() const { return foo_ptr.get(); } // 唯一允许修改Foo的入口 void set_number(int num) { if (foo_ptr) { foo_ptr->set_number(num); } } };
用户拿到const Foo*后,只能访问Foo的只读接口,没法直接修改对象,所有权始终握在ManageFoo手里。
方案2:封装只读接口(完全隐藏指针)
如果你彻底不想暴露指针,可以把Foo的所有只读操作都封装到ManageFoo里,完全屏蔽底层的指针细节:
class ManageFoo { private: std::unique_ptr<Foo> foo_ptr; public: // 直接提供Foo的只读数据访问 int get_foo_number() const { return foo_ptr ? foo_ptr->get_number() : 0; // 假设Foo有get_number()方法 } // 唯一的修改入口 void set_number(int num) { if (foo_ptr) { foo_ptr->set_number(num); } } // 其他需要的只读操作都在这里添加,比如get_foo_name()之类的 };
这种方式最符合面向对象的封装原则,用户不需要知道Foo的存在,只和ManageFoo交互。
方案3:改用std::shared_ptr实现智能指针只读访问
如果你坚持要用智能指针返回,可以把内部的unique_ptr换成shared_ptr,然后返回std::shared_ptr<const Foo>:
class ManageFoo { private: std::shared_ptr<Foo> foo_ptr; public: // 隐式转换为shared_ptr<const Foo>,用户只能访问只读接口 std::shared_ptr<const Foo> getFoo() const { return foo_ptr; } void set_number(int num) { if (foo_ptr) { foo_ptr->set_number(num); } } };
用户拿到的shared_ptr<const Foo>只能调用Foo的const成员,没法修改对象,同时ManageFoo仍然是对象的主要所有者(只要ManageFoo存在,对象就不会被释放)。
内容的提问来源于stack exchange,提问作者rdabra
相关产品推荐
相关产品推荐

