核心概念:
代码示例:动态多态(动物叫声模拟)
#include
#include
// 抽象基类
class Animal {
public:
virtual void speak() const = 0;
virtual ~Animal() = default;
};
// 具体子类
class Cat : public Animal {
public:
void speak() const override {
std::cout << "喵喵喵~\n";
}
};
class Dog : public Animal {
public:
void speak() const override {
std::cout << "汪汪汪!\n";
}
};
// 测试用例
int main() {
std::unique_ptr<Animal> pets[] = {
std::make_unique<Cat>(),
std::make_unique<Dog>()
};
for (const auto& pet : pets) {
pet->speak(); // 运行时动态绑定
}
}
编译运行:
g++ -std=c++17 dynamic_poly.cpp -o dynamic_poly
./dynamic_poly
输出结果:
喵喵喵~
汪汪汪!
核心概念:
代码示例:几何图形面积计算
#include
#include
// CRTP基类模板
template <typename Derived>
class Shape {
public:
double area() const {
return static_cast<const Derived*>(this)->calc_area();
}
};
// 圆形实现
class Circle : public Shape<Circle> {
double radius;
public:
Circle(double r) : radius(r) {}
double calc_area() const {
return M_PI * radius * radius;
}
};
// 正方形实现
class Square : public Shape<Square> {
double side;
public:
Square(double s) : side(s) {}
double calc_area() const {
return side * side;
}
};
// 通用面积打印函数
template <typename T>
void print_area(const Shape<T>& shape) {
std::cout << "面积: " << shape.area() << "\n";
}
// 测试用例
int main() {
Circle c(3.0);
Square s(4.0);
print_area(c); // 编译期绑定
print_area(s);
}
编译运行:
g++ -std=c++17 crtp_demo.cpp -o crtp_demo
./crtp_demo
输出结果:
面积: 28.2743
面积: 16
核心概念:
代码示例:可配置的数组处理器
#include
#include
#include
// 打印策略
struct ConsolePrinter {
template <typename T>
static void print(const std::vector<T>& vec) {
for (const auto& x : vec) {
std::cout << x << " ";
}
std::cout << "\n";
}
};
struct CompactPrinter {
template <typename T>
static void print(const std::vector<T>& vec) {
std::cout << "[";
for (size_t i=0; i<vec.size(); ++i) {
std::cout << vec[i] << (i+1 < vec.size() ? "," : "");
}
std::cout << "]\n";
}
};
// 数组处理器模板
template <typename T, typename PrintPolicy = ConsolePrinter>
class ArrayProcessor {
std::vector<T> data;
public:
explicit ArrayProcessor(std::vector<T>&& input) : data(std::move(input)) {}
void process_and_print() {
std::sort(data.begin(), data.end());
PrintPolicy::print(data);
}
};
// 测试用例
int main() {
std::vector<int> numbers{5, 2, 7, 1, 9};
// 使用默认控制台打印策略
ArrayProcessor<int> processor1(numbers);
processor1.process_and_print();
// 使用紧凑打印策略
ArrayProcessor<int, CompactPrinter> processor2(std::move(numbers));
processor2.process_and_print();
}
编译运行:
g++ -std=c++17 policy_pattern.cpp -o policy_demo
./policy_demo
输出结果:
1 2 5 7 9
[1,2,5,7,9]
多态类型选择:
CRTP精髓:
template <typename Derived>
class Base {
void interface() {
static_cast<Derived*>(this)->implementation();
}
};
通过模板参数传递派生类类型,实现编译期多态调度
策略模式优势:
模板元编程技巧:
static_assert
进行编译期检查std::enable_if
实现SFINAEconstexpr
实现编译期计算拓展练习:
关于静态多态与动态多态,以下说法正确的有:
A. 动态多态通过虚函数表实现运行时类型解析
B. 静态多态会生成更多模板实例化代码
C. 静态多态支持协变返回类型
D. 动态多态的类型检查发生在编译期
模板实现静态多态的优势包括:
A. 零运行时开销
B. 支持鸭子类型
C. 更好的二进制兼容性
D. 支持运行时类型识别(RTTI)
关于C++概念(Concepts),正确的描述是:
A. 可以替代SFINAE技术
B. 必须与模板参数一起声明
C. 支持对模板参数的语义约束
D. 会阻止隐式类型转换
以下哪些模式适合用模板静态多态实现:
A. 策略模式
B. 观察者模式
C. 访问者模式
D. 工厂方法模式
模板元编程可以实现:
A. 编译期数值计算
B. 类型特征萃取
C. 运行时异常处理
D. 代码生成优化
CRTP模式的特点包括:
A. 通过基类模板参数化派生类
B. 实现编译期多态
C. 需要虚函数支持
D. 常用于性能优化场景
关于类型擦除技术:
A. std::function使用了类型擦除
B. 需要运行时类型信息
C. 可以通过模板和虚函数结合实现
D. 完全避免动态内存分配
模板特化的正确应用场景包括:
A. 优化特定类型的算法实现
B. 处理边界条件
C. 实现类型分发
D. 替代函数重载
可变参数模板可用于:
A. 实现类型安全的printf
B. 构造元组类型
C. 编译期参数包展开
D. 替代运行时可变参数
编译期多态的限制包括:
A. 无法处理运行时类型变化
B. 错误信息可读性差
C. 增加代码膨胀风险
D. 不支持递归算法
实现编译期策略选择器
设计一个模板类Executor
,根据策略类型在编译期选择不同的算法实现:
Sequential
和Parallel
两种策略类型安全的访问者模式
使用可变参数模板实现一个类型安全的访问者模式:
概念约束的数学库
开发一个数学函数库,使用概念约束:
Arithmetic
概念要求数值类型编译期工厂模式
创建编译期对象工厂:
高性能静态多态容器
设计一个支持静态多态的容器:
AB
A正确:虚函数表是动态多态的基础机制
B正确:模板实例化会生成多个版本代码
C错误:协变返回是动态多态特性
D错误:动态多态类型检查在运行时
AB
A正确:无虚函数调用开销
B正确:基于接口的隐式约定
C错误:模板实例化可能影响二进制兼容
D错误:RTTI属于运行时特性
AC
A正确:概念可替代复杂的SFINAE
C正确:概念提供语义约束
B错误:概念可独立定义
D错误:概念不阻止合法转换
AC
A正确:策略模式常用模板实现
C正确:访问者可用可变参数模板实现
B/D更适合动态多态
ABD
A正确:如斐波那契数列编译期计算
B正确:类型特征萃取是典型应用
D正确:通过模板生成优化代码
C错误:异常处理是运行时机制
ABD
A正确:CRTP基类以派生类为模板参数
B正确:编译期多态典型实现
D正确:常用于避免虚函数开销
C错误:CRTP不需要虚函数
ABC
A正确:std::function内部使用类型擦除
B正确:需要存储类型信息
C正确:典型实现方式
D错误:通常需要动态分配
ABC
A正确:特化优化特定类型
B正确:处理边界条件常用
C正确:类型分发典型应用
D错误:重载与特化不同机制
ABC
A正确:如格式化库实现
B正确:std::tuple的基础
C正确:参数包展开机制
D错误:编译期与运行时机制不同
ABC
A正确:编译期确定类型
B正确:模板错误信息复杂
C正确:多个实例导致代码膨胀
D错误:支持递归如元编程
template <typename Policy>
requires std::same_as<Policy, Sequential> || std::same_as<Policy, Parallel>
class Executor {
Policy strategy;
public:
void execute() {
strategy.implement();
}
};
struct Sequential {
void implement() { /* 串行实现 */ }
};
struct Parallel {
void implement() { /* 并行实现 */ }
};
// 测试
int main() {
Executor<Sequential> seq;
seq.execute(); // 调用串行版本
Executor<Parallel> par;
par.execute(); // 调用并行版本
// Executor invalid; // 编译错误
}
template <typename... Ts>
struct Visitor : Ts... {
using Ts::operator()...;
};
template <typename... Ts>
Visitor(Ts...) -> Visitor<Ts...>;
template <typename T, typename... Handlers>
void visit(T&& value, Handlers&&... hs) {
auto v = Visitor{std::forward<Handlers>(hs)...};
v(std::forward<T>(value));
}
// 使用示例
struct Circle { int radius; };
struct Square { int side; };
int main() {
std::variant<Circle, Square> shape = Circle{5};
visit(shape,
[](const Circle& c) { std::cout << "Circle: " << c.radius; },
[](const Square& s) { std::cout << "Square: " << s.side; });
// 未处理类型会编译报错
}
template <typename T>
concept Arithmetic = requires(T a, T b) {
{ a + b } -> std::convertible_to<T>;
{ a * b } -> std::convertible_to<T>;
std::is_arithmetic_v<T>;
};
template <Arithmetic T>
T add(T a, T b) {
return a + b;
}
// 自定义符合概念的类型
struct Complex {
double real, imag;
Complex operator+(const Complex& other) const {
return {real + other.real, imag + other.imag};
}
};
int main() {
add(3, 5); // OK
add(2.5, 3.7); // OK
add(Complex{}, Complex{}); // OK
// add("a", "b"); // 编译错误
}
template <typename... Products>
class Factory {
template <typename T>
static T* create() {
static_assert((std::is_base_of_v<Product, T> || ...),
"Unregistered product type");
return new T();
}
};
class Product {};
class Widget : public Product {};
class Gadget : public Product {};
int main() {
auto w = Factory<Widget, Gadget>::create<Widget>(); // OK
// auto x = Factory::create(); // 编译错误
}
template <typename Derived>
class Drawable {
public:
void draw() const {
static_cast<const Derived*>(this)->draw_impl();
}
};
class Circle : public Drawable<Circle> {
public:
void draw_impl() const { /* 绘制圆 */ }
};
class Square : public Drawable<Square> {
public:
void draw_impl() const { /* 绘制方 */ }
};
template <typename T>
requires std::is_base_of_v<Drawable<T>, T>
class ShapeContainer {
std::vector<T> shapes;
public:
void drawAll() {
for (auto& s : shapes) {
s.draw();
}
}
};
int main() {
ShapeContainer<Circle> circles;
circles.drawAll();
// ShapeContainer invalid; // 编译错误
}
g++ -std=c++20 -o test test.cpp