使用CRTP实现无虚函数回调时编译器找不到基类非虚函数问题
问题原因
这个编译错误是C标准规定的**名字隐藏(Name Hiding)**规则导致的,和你使用的CRTP范式、MSVC编译器都没有关系,属于C的常规语义要求:
当派生类Bar中定义了任意一个名为DoAct的成员函数时,编译器在Bar的类作用域内查找DoAct名称时,只要匹配到派生类自己的DoAct(Y*)就会停止向上查找基类Foo的作用域,因此基类中定义的DoAct(X*)、DoAct(Y*)两个重载版本根本不会进入本次函数调用的候选列表。
此时唯一的候选函数只有Bar::DoAct(Y*),传入X*类型参数自然会触发类型不匹配的编译错误。
解决方法
最简单的方案是在Bar类中主动引入基类的DoAct重载集合,不需要额外重写DoAct(X*):
struct Bar : Foo<Bar> { using Foo<Bar>::DoAct; // 引入基类所有DoAct重载到当前作用域 void DoAct(Y*) {} };
你注释掉的自行实现Bar::DoAct(X*)的方案也可以正常工作,本质是在Bar的作用域内提供了参数匹配的重载版本,不需要再查找基类作用域。
补充说明
名字隐藏规则的设计初衷是避免派生类意外继承基类的重载导致预期外的函数调用,所有符合C++标准的编译器都会执行这个检查,不是MSVC的独有行为。
内容的提问来源于stack exchange,提问作者Dess
相关产品推荐
相关产品推荐

