You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用shared_from_this()为何必须用this->?跨平台编译异常解析

为什么调用shared_from_this()而非this->shared_from_this()时GCC/Clang编译失败?

在跨平台项目中,我有部分代码在Visual Studio编译正常,但调用shared_from_this()而非this->shared_from_this()时,GCC和Clang编译失败。

第一个最小示例代码

#include <memory>

struct class1: public std::enable_shared_from_this<class1>
{
    template<typename T>
    struct class2: public std::enable_shared_from_this<class2<T>>
    {
        void func()
        {
            this->shared_from_this(); // 此写法正常
            shared_from_this(); // 此写法报错???
        }
    };
};

void foo()
{
    class1::class2<int>().func();
}

GCC编译报错

$ g++ -c bug.cpp
bug.cpp: In instantiation of ‘void class1::class2<T>::func() [with T = int]’:
bug.cpp:18:28:   required from here
bug.cpp:11:41: error: cannot call member function ‘std::shared_ptr<_Tp> std::enable_shared_from_this<_Tp>::shared_from_this() [with _Tp = class1]’ without object
   11 |                         shared_from_this(); // this gives an error ???
      |                         ~~~~~~~~~~~~~~~~^~

Clang编译报错

$ clang++ -c bug2.cpp
bug.cpp:11:4: error: call to non-static member function without an object argument
                        shared_from_this(); // this gives an error ???
                        ^~~~~~~~~~~~~~~~
bug.cpp:18:24: note: in instantiation of member function 'class1::class2<int>::func' requested here
        class1::class2<int>().func();
                              ^

移除外部类后的简化示例代码

#include <memory>

template<typename T>
struct class1: public std::enable_shared_from_this<class1<T>>
{
    void func()
    {
        this->shared_from_this(); // 此写法正常
        shared_from_this(); // 此写法报错???
    }
};

void foo()
{
    class1<int>().func();
}

GCC编译报错

$ g++ -c bug1.cpp
bug1.cpp: In member function ‘void class1<T>::func()’:
bug1.cpp:9:17: error: there are no arguments to ‘shared_from_this’ that depend on a template parameter, so a declaration of ‘shared_from_this’ must be available [-fpermissive]
    9 |                 shared_from_this(); // this gives an error ???
      |                 ^~~~~~~~~~~~~~~~
bug1.cpp:9:17: note: (if you use ‘-fpermissive’, G++ will accept your code, but allowing the use of an undeclared name is deprecated)

Clang编译报错

$ clang++ -c bug1.cpp
bug1.cpp:9:3: error: use of undeclared identifier 'shared_from_this'
                shared_from_this(); // this gives an error ???

问题

我的代码确实存在问题吗(若存在,原因是什么)?还是GCC和Clang存在常见bug?


解答

这不是编译器bug,你的代码确实不符合C++标准规定,核心原因是模板上下文的名字查找规则:

  • 对于普通非模板类,编译器会自动在基类中查找未限定的成员名;但对于模板类(或嵌套在模板中的类),编译器不会自动去依赖基类(即基类类型依赖于模板参数,比如std::enable_shared_from_this<class2<T>>)中查找未限定的成员名。
  • shared_from_this()是基类std::enable_shared_from_this的成员函数,直接写shared_from_this()时,在模板上下文中编译器无法确定这个名字来自依赖基类,会尝试在当前作用域或全局作用域查找,找不到就报错。
  • 而this->shared_from_this()明确告知编译器:要从当前对象的基类中查找该成员,触发依赖于模板参数的名字查找,编译器会延迟到模板实例化时再去基类中查找,因此能正确定位到目标函数。

在第一个嵌套类示例中,GCC报错提到std::enable_shared_from_this<class1>,是因为编译器找不到目标成员时,会尝试去外部类class1的基类中查找,但该基类的shared_from_this属于class1,和当前class2<T>实例无关,因此报“无对象调用成员函数”的错误。

Visual Studio的编译器在名字查找规则上做了宽松实现,默认会在依赖基类中查找未限定成员名,因此能编译通过,但这并不符合标准规范。


内容的提问来源于stack exchange,提问作者Mario Klebsch

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 09:07:51