From fa7deae8922dd35f6a87486ef1b61daff35c62bc Mon Sep 17 00:00:00 2001 From: mq-b <3326284481@qq.com> Date: Fri, 6 Sep 2024 10:41:32 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20CRTP=20=E7=9A=84=E4=B8=80?= =?UTF-8?q?=E8=8A=82=E5=86=85=E5=AE=B9=EF=BC=8C=E8=A1=A5=E5=85=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...06\344\270\216\344\275\277\347\224\250.md" | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git "a/md/\346\211\251\345\261\225\347\237\245\350\257\206/CRTP\347\232\204\345\216\237\347\220\206\344\270\216\344\275\277\347\224\250.md" "b/md/\346\211\251\345\261\225\347\237\245\350\257\206/CRTP\347\232\204\345\216\237\347\220\206\344\270\216\344\275\277\347\224\250.md" index d75cf7e..4589851 100644 --- "a/md/\346\211\251\345\261\225\347\237\245\350\257\206/CRTP\347\232\204\345\216\237\347\220\206\344\270\216\344\275\277\347\224\250.md" +++ "b/md/\346\211\251\345\261\225\347\237\245\350\257\206/CRTP\347\232\204\345\216\237\347\220\206\344\270\216\344\275\277\347\224\250.md" @@ -72,6 +72,96 @@ class X : public Base { }; ``` +## 使用 CRTP 模式实现静态多态性并复用代码 + +虚函数的价值在于,作为一个参数传入其他函数时 可以复用那个函数里的代码,而不需要在需求频繁变动与增加的时候一直修改。 + +```cpp +class BaseVirtual { +public: + virtual void addWater(int amount) = 0; // 纯虚函数声明 +}; + +class XVirtual : public BaseVirtual { +public: + void addWater(int amount) override { + std::cout << "XVirtual 设备加了 " << amount << " 毫升水\n"; + } +}; + +class YVirtual : public BaseVirtual { +public: + void addWater(int amount) override { + std::cout << "YVirtual 设备加了 " << amount << " 毫升水\n"; + } +}; + +// 接口,父类的引用 +void processWaterAdditionVirtual(BaseVirtual& r, int amount) { + if (amount > 0) { + r.addWater(amount); + } else { + std::cerr << "无效数量: " << amount << '\n'; // 错误处理 + } +} + +int main(){ + XVirtual xVirtual; + YVirtual yVirtual; + + processWaterAdditionVirtual(xVirtual, 50); + processWaterAdditionVirtual(yVirtual, 100); + processWaterAdditionVirtual(xVirtual, -10); +} +``` + +> [运行](https://godbolt.org/z/Wjfx1TfMh)测试。 + +**CRTP 同样可以,并且还是静态类型安全,这不成问题:** + +```cpp +template +class Base { +public: + void addWater(int amount) { + static_cast(this)->impl_addWater(amount); + } +}; + +class X : public Base { +friend Base; + void impl_addWater(int amount) { + std::cout << "X 设备加了 " << amount << " 毫升水\n"; + } +}; +class Y : public Base { +friend Base; + void impl_addWater(int amount) { + std::cout << "Y 设备加了 " << amount << " 毫升水\n"; + } +}; + +template +void processWaterAddition(Base& r, int amount) { + if (amount > 0) { + r.addWater(amount); + } else { + std::cerr << "无效数量: " << amount << '\n'; + } +} + +int main() { + X x; + Y y; + + processWaterAddition(x, 50); + processWaterAddition(y, 100); + processWaterAddition(x, -10); +} +``` + +> [运行](https://godbolt.org/z/YoabKjMhh)测试。 + ## C++23 的改动-显式对象形参 C++23 引入了**显式对象形参**,让我们的 `CRTP` 的形式也出现了变化: