拓冰建站拓冰建站
首页 / 资讯中心 / 正文

CRTP 编译期多态与静态接口:没有虚函数也能多态

继承 + 虚函数不是 C++ 里实现「一套接口、多种实现」的唯一路子。如果你想要的是编译期就定下来的多态——没有运行期查虚表(virtual table,vtable)、调用能被内联(inline)、对象还更小——CRTP 就是这个需求的标准答案。这篇用真跑出来的sizeof和计数器实例,把 CRTP 到底是什么、为什么快、代价是什么讲清楚。1. 引子:虚函数到底「贵」在哪写惯了面向对象的人,要统一操作一批类型第一反应是抽个基类、把行为声明成virtual:structShape{virtualvoiddraw()=0;virtual~Shape()=default;};structCircle:Shape{voiddraw()override{/* ... */}};这没问题,但隐藏三笔账:每个对象多一个 vptr(虚表指针)、每次调用draw()都要「取 vptr → 查表 → 跳转到函数」的间接跳转(indirect branch,会打分支预测)、整个类层级多了虚表数据。对性能敏感、或对象极多的场景,这三笔账可能不划算。CRTP 的卖点就是——把这些账全免了,代价是把「多态」从运行期挪到编译期。官方文档:Curiously recurring template pattern — cppreference2. CRTP 长什么样:派生类把自己喂给基类CRTP 的骨架就一句话:基类是个模板,派生类继承「以自己为模板参数的基类」。// crtp_basic.cpp — 编译: g++ -std=c++17 -Wall -O2 crtp_basic.cpp -o cb#includecstdiotemplateclassDerivedstructShape{voiddraw()const{static_castconstDerived*(this)-draw_impl();}};structCircle:ShapeCircle{voiddraw_impl()const{std::puts("Circle::draw");}};structSquare:ShapeSquare{voiddraw_impl()const{std::puts("Square::draw");}};intmain(){Circle c;c.draw();Square s;s.draw();
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门