C++派生类中重载函数未被调用的原因及解决方法
问题原因
- 名字查找规则限制:基类
Compare的operator()中调用compare(a, b)时,名字查找只会在基类作用域内匹配符号,编译期就会绑定到基类自己的compare模板函数,不会查找派生类作用域的同名函数。派生类的compare函数只是隐藏了基类的同名函数,对基类内部的调用不可见。 - 无动态绑定逻辑:
compare函数不是虚函数,即使派生类定义了同名重载,运行时也不会触发动态分发,基类调用的永远是自身作用域内的函数实现。
修复方案
推荐使用CRTP(奇异递归模板模式)实现编译期静态多态,无虚函数开销即可让基类调用派生类的重载实现,修改后的代码如下:
#include <stdio.h> struct A {}; // 基类改为CRTP模板,接收派生类作为模板参数 template <typename Derived> struct Compare { template <typename T> bool operator()(const T& a, const T& b) const { printf("from operator()\n"); // 强转为派生类指针,调用派生类的compare实现 return static_cast<const Derived*>(this)->compare(a, b); } protected: // 通用比较逻辑放到protected,派生类可按需 fallback 调用 template <typename T> bool base_compare(const T& a, const T& b) const { printf("from base compare template \n"); return true; } }; // 派生类继承时传入自身类型给CRTP基类 struct CompareDerived : public Compare<CompareDerived> { // 重载A类型的比较逻辑 bool compare(const A& n, const A& p) const { printf("from derived overload\n"); return true; } // 通用类型回退到基类实现 template <typename T> bool compare(const T& a, const T& b) const { return base_compare(a, b); } }; template <typename T, typename Comp = CompareDerived> bool trigger (const T& a, const T&b, const Comp& compare = Comp()) { return compare(a, b); } int main() { A a1, a2; CompareDerived m; trigger<A, CompareDerived>(a1, a2, m); return 0; }
修改后运行输出结果为:
from operator() from derived overload
如果不需要支持泛型扩展,也可以在基类声明针对A类型的虚函数,派生类重写该虚函数即可实现调用,不过该方案仅支持提前约定的类型,扩展性弱于CRTP方案。
内容的提问来源于stack exchange,提问作者pepero
相关产品推荐
相关产品推荐

