C++(mixins 混入模式)

🎯 什么是 Mixins?

Mixins 是一种组合优于继承 的设计模式,通过多重继承将功能片段(而非完整的类)组合到目标类中。

🧩 Mixin vs 普通继承:

普通继承 Mixin 继承
class Dog : public Animal class MyWidget : public Draggable, public Resizable
表达"是一个"关系 表达"具有...特性"关系
单一职责(一个父类) 多重特性(多个 mixin)

🔥 C++ Mixins 核心原则

  1. 只提供功能,不封装状态(可选)
  2. CRTP (Curiously Recurring Template Pattern) 优化性能
  3. 非虚函数为主(避免虚函数开销)
  4. 组合而非继承

🧪 示例 1:基础 Mixin(无状态)

复制代码
   // mixable.hpp
   template<typename T>
   struct Draggable {
       void drag(int dx, int dy) {
           auto* self = static_cast<T*>(this);
           self->x += dx;  // 假设 T 有 x, y 成员
           self->y += dy;
           std::cout << "Dragged to (" << self->x << ", " << self->y << ")\n";
       }
   };

   template<typename T>
   struct Loggable {
       void log(const std::string& msg) {
           auto* self = static_cast<T*>(this);
           std::cout << "[" << typeid(*self).name() << "] " << msg << std::endl;
       }
   };

   // 使用 mixins
   class Widget {
   public:
       int x = 0, y = 0;
       std::string name = "Widget";
   };

   class EnhancedWidget : public Widget,
                          public Draggable<EnhancedWidget>,
                          public Loggable<EnhancedWidget> {
   public:
       void click() {
           log("Clicked!");
           drag(10, 10);
       }
   };

   // 使用
   EnhancedWidget w;
   w.click();  // [class EnhancedWidget] Clicked!
               // Dragged to (10, 10)

🧪 示例 2:带状态的 Mixin(实用)

复制代码
   // mixins_with_state.hpp
   template<typename T>
   struct TimestampMixin {
   protected:
       time_t created_at = time(nullptr);
       
   public:
       time_t get_creation_time() const { return created_at; }
       std::string get_formatted_time() const {
           char buffer[100];
           strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S",
                   localtime(&created_at));
           return buffer;
       }
   };

   template<typename T>
   struct IdMixin {
   private:
       static inline int next_id = 0;
       int id;

   protected:
       IdMixin() : id(++next_id) {}
       
   public:
       int get_id() const { return id; }
   };

   // 组合使用
   class DataProcessor : public TimestampMixin<DataProcessor>,
                         public IdMixin<DataProcessor> {
   public:
       void process() {
           std::cout << "Processing ID: " << get_id() 
                     << " at " << get_formatted_time() << std::endl;
       }
   };

   DataProcessor p1, p2;
   p1.process(); // Processing ID: 1 at 2026-04-25 15:42:xx
   p2.process(); // Processing ID: 2 at 2026-04-25 15:42:xx

🧪 示例 3:CRTP + Mixins(高性能)

复制代码
   // crtp_mixins.hpp
   template<typename Derived>
   struct ArithmeticMixin {
       // 返回派生类型,支持链式调用
       Derived operator+(const Derived& other) const {
           auto result = static_cast<const Derived&>(*this);
           result.value += other.value;  // 假设派生类有 value 成员
           return result;
       }
       
       Derived& operator+=(const Derived& other) {
           static_cast<Derived&>(*this).value += other.value;
           return static_cast<Derived&>(*this);
       }
   };

   template<typename Derived>
   struct PrintableMixin {
       void print() const {
           const auto& self = static_cast<const Derived&>(*this);
           std::cout << "Value: " << self.value << std::endl;
       }
   };

   // 使用 CRTP Mixins
   class Number : public ArithmeticMixin<Number>,
                  public PrintableMixin<Number> {
   public:
       int value;
       Number(int v = 0) : value(v) {}
   };

   Number a(5), b(3);
   auto c = a + b;  // 使用 ArithmeticMixin
   c.print();       // 使用 PrintableMixin

📌 Mixins 的优势

代码复用 :功能模块化,可重复使用

灵活组合 :按需选择特性

编译期多态 :无虚函数性能损失(CRTP)

类型安全:模板保证编译期检查

缺点
6. 继承层次复杂(调试困难)
7. 模板代码膨胀
8. 学习曲线陡峭

相关推荐
澈2073 小时前
C++并查集:高效解决连通性问题
java·c++·算法
郝学胜-神的一滴4 小时前
Qt 入门 01-01:从零基础到商业级客户端实战
开发语言·c++·qt·程序人生·软件构建
测试员周周5 小时前
【Appium 系列】第06节-页面对象实现 — LoginPage 实战
开发语言·前端·人工智能·python·功能测试·appium·测试用例
宏笋5 小时前
C++ thread的detach()方法详解
c++
旖-旎5 小时前
深搜练习(单词搜索)(12)
c++·算法·深度优先·力扣
摇滚侠5 小时前
@Autowired 和 @Resource 的区别
java·开发语言
largecode5 小时前
打电话时,怎么让号码显示自己的品牌名称?办理号码认证服务流程
笔记·百度·微信·课程设计·微信公众平台·facebook·新浪微博
Wy_编程5 小时前
go语言中的结构体
开发语言·后端·golang
SeaTunnel5 小时前
(八)收官篇 | 数据平台最后一公里:数据集成开发设计与上线治理实战
java·大数据·开发语言·白鲸开源
大卡片6 小时前
C++的基础知识点
开发语言·c++