🎯 什么是 Mixins?
Mixins 是一种组合优于继承 的设计模式,通过多重继承将功能片段(而非完整的类)组合到目标类中。
🧩 Mixin vs 普通继承:
| 普通继承 | Mixin 继承 |
|---|---|
class Dog : public Animal |
class MyWidget : public Draggable, public Resizable |
| 表达"是一个"关系 | 表达"具有...特性"关系 |
| 单一职责(一个父类) | 多重特性(多个 mixin) |
🔥 C++ Mixins 核心原则
- 只提供功能,不封装状态(可选)
- CRTP (Curiously Recurring Template Pattern) 优化性能
- 非虚函数为主(避免虚函数开销)
- 组合而非继承
🧪 示例 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. 学习曲线陡峭