C++派生类从*this获取shared_ptr的歧义问题及解决方法
你遇到的错误是因为BBB同时继承了AAA(间接继承std::enable_shared_from_this<AAA>)和std::enable_shared_from_this<BBB>,两个基类都提供了shared_from_this成员函数,编译器无法确定调用哪个版本,因此出现歧义。下面给出两种可行的解决方案:
方案一:明确指定要调用的shared_from_this版本
在派生类中直接限定调用对应模板版本的shared_from_this,避免编译器的歧义查找:
#include <memory> struct AAA : std::enable_shared_from_this<AAA> { auto getA() -> std::shared_ptr<AAA> { return this->shared_from_this(); } }; struct BBB : AAA, std::enable_shared_from_this<BBB> { auto getB() -> std::shared_ptr<BBB> { // 明确调用BBB对应的enable_shared_from_this版本 return std::enable_shared_from_this<BBB>::shared_from_this(); } };
这种方法简单直接,但本质上仍存在两个enable_shared_from_this实例,虽能解决编译问题,但不够优雅。
方案二:避免多重继承enable_shared_from_this(推荐)
让派生类不再单独继承std::enable_shared_from_this,而是通过基类的shared_from_this获取指针后,用std::static_pointer_cast转换为派生类的shared_ptr,从根源上消除歧义:
#include <memory> #include <functional> struct AAA : std::enable_shared_from_this<AAA> { auto set_attrZ(int val) -> std::shared_ptr<AAA> { // 实现属性设置逻辑 return shared_from_this(); } auto set_attrK(int val) -> std::shared_ptr<AAA> { // 实现属性设置逻辑 return shared_from_this(); } }; struct BBB : AAA { auto set_attrA(int val) -> std::shared_ptr<BBB> { // 实现属性设置逻辑 return std::static_pointer_cast<BBB>(shared_from_this()); } auto set_attrB(int val) -> std::shared_ptr<BBB> { // 实现属性设置逻辑 return std::static_pointer_cast<BBB>(shared_from_this()); } auto set_callback(std::function<void()> cb) -> std::shared_ptr<BBB> { // 实现回调设置逻辑 return std::static_pointer_cast<BBB>(shared_from_this()); } auto do_some_work() -> std::shared_ptr<BBB> { // 实现工作逻辑 return std::static_pointer_cast<BBB>(shared_from_this()); } };
这种方案完全满足你的链式调用需求:
// 链式调用示例 auto a = std::make_shared<AAA>() -> set_attrZ(1) -> set_attrK(2); auto b = std::make_shared<BBB>() -> set_attrA(1) -> set_attrB(2) -> set_callback([](){ /* ... */ }); std::make_shared<BBB>() -> set_attrA(1) -> set_attrB(2) -> set_callback([](){ /* ... */ }) -> do_some_work();
原理说明
当你用std::make_shared<BBB>()创建实例时,std::enable_shared_from_this<AAA>内部的weak_ptr会被正确关联到这个shared_ptr的控制块。调用shared_from_this()会返回std::shared_ptr<AAA>,通过std::static_pointer_cast转换为std::shared_ptr<BBB>是安全的——因为当前实例确实是BBB类型。
内容的提问来源于stack exchange,提问作者elcuco
相关产品推荐
相关产品推荐

