GCC编译报invalid use of member function错误,Clang可正常编译
问题重现
你的代码在Clang下编译运行正常,但GCC报出如下错误:
709568706/source.cpp: In function ‘int main()’:
709568706/source.cpp:28:32: error: invalid use of member function ‘static void MessagePoller::poll_timer()’ (did you forget the ‘()’ ?)
std::cout << (void*)m_sut->poll_timer << std::endl;
~~~~^
核心代码结构:
#include <iostream> #include <memory> class MessagePoller { protected: static void poll_timer() { std::cout << "Poll timer Base called\n"; } }; class TestMessagePoller : public MessagePoller { public: using MessagePoller::poll_timer; }; typedef std::shared_ptr<TestMessagePoller> TestMessagePollerPtr; int main() { TestMessagePollerPtr m_sut = TestMessagePollerPtr(new TestMessagePoller()); std::cout << (void*)m_sut->poll_timer << std::endl; // GCC报错行 return 0; }
差异原因分析
静态成员函数的本质:静态成员函数不属于任何对象实例,它的地址获取逻辑和全局函数类似。C++标准允许通过
&类名::成员函数直接取地址,也允许通过对象/指针访问时,将成员函数名隐式转换为函数指针(即obj.member或ptr->member等价于类名::member)。GCC的严格解析逻辑:当你用
using MessagePoller::poll_timer将基类的protected静态成员引入子类public作用域时,GCC在处理m_sut->poll_timer时,优先将其解析为成员函数调用的语法(默认认为你漏写了()来执行函数),没有识别出你要获取函数地址的意图。这种严格性是GCC对using声明引入成员的访问语法解析规则导致的。Clang的宽松解析逻辑:Clang正确识别了
m_sut->poll_timer的意图是获取静态成员函数的地址——它将通过对象指针访问的静态成员函数名,直接等价于TestMessagePoller::poll_timer,进而允许其隐式转换为函数指针,完全符合C++标准对静态成员的访问规则。
为什么修改后能解决问题
当你移除using声明并将基类的poll_timer改为public时,TestMessagePoller直接继承了public的静态成员函数,此时GCC会直接将m_sut->poll_timer解析为静态成员函数名,允许其隐式转换为函数指针,因此不会再报错。
内容的提问来源于stack exchange,提问作者Bilal Ahmed

