1. 函数对象与适配器的本质解析
第一次接触STL算法时,很多人都会有这样的困惑:为什么std::sort()可以接受函数指针、lambda甚至自定义类型作为比较器?为什么std::bind能神奇地改变函数参数顺序?这些魔法般的特性背后,正是函数对象(Function Object)和适配器(Adapter)在发挥作用。
函数对象本质上是一个行为类似函数的类实例。通过重载operator(),我们可以让类对象拥有函数般的调用能力。这种设计模式在C++标准库中随处可见:
cpp复制struct Square {
int operator()(int x) const {
return x * x;
}
};
Square sq; // 创建函数对象
cout << sq(5); // 输出25,像函数一样使用
适配器则是包装现有函数或函数对象的工具,它能改变接口形式却不改变核心逻辑。比如std::bind就是一种典型的适配器,它允许我们:
- 重新排序参数位置
- 固定部分参数值
- 将成员函数转为可调用对象
cpp复制void printSum(int a, int b) {
cout << a + b;
}
// 使用bind适配参数顺序
auto reversedPrint = bind(printSum, _2, _1);
reversedPrint(3, 5); // 输出8,相当于printSum(5,3)
关键理解:函数对象将算法策略对象化,适配器则提供了灵活的接口转换能力。二者配合使得STL算法能像"活物"一样适应各种场景需求。
2. STL中的经典函数对象体系
标准库为我们构建了完整的函数对象体系,主要分为以下几类:
2.1 算术运算函数对象
cpp复制plus<int> add;
cout << add(3,5); // 输出8
multiplies<double> mul;
cout << mul(2.5,4); // 输出10.0
这些函数对象通常用于std::accumulate等算法中:
cpp复制vector<int> v {1,2,3,4};
int product = accumulate(v.begin(), v.end(), 1, multiplies<int>());
// 计算1*2*3*4=24
2.2 比较函数对象
cpp复制greater<int> gt;
cout << gt(5,3); // 输出1(true)
vector<string> words {"apple", "banana", "cherry"};
sort(words.begin(), words.end(), greater<string>());
// 按字典序降序排列
2.3 逻辑运算函数对象
cpp复制logical_and<bool> andOp;
cout << andOp(true, false); // 输出0
vector<bool> flags {true, false, true};
auto allTrue = all_of(flags.begin(), flags.end(), logical_and<bool>());
2.4 函数对象适配器
标准库提供了几种强大的适配器工具:
2.4.1 bind适配器
cpp复制using namespace std::placeholders;
void logMessage(const string& msg, int severity) {
cout << "[" << severity << "] " << msg;
}
auto logWarning = bind(logMessage, _1, 2); // 固定severity为2
logWarning("Disk almost full"); // 输出"[2] Disk almost full"
2.4.2 mem_fn适配器
cpp复制class Widget {
public:
void draw() const { cout << "Drawing widget\n"; }
};
vector<Widget> widgets(3);
for_each(widgets.begin(), widgets.end(), mem_fn(&Widget::draw));
2.4.3 not1/not2否定器
cpp复制vector<int> nums {5,3,8,1,7};
auto isEven = [](int x) { return x%2 == 0; };
// 计算奇数个数
int oddCount = count_if(nums.begin(), nums.end(), not1(ptr_fun(isEven)));
3. 自定义函数对象的高级技巧
3.1 状态保持函数对象
与普通函数不同,函数对象可以维护状态:
cpp复制class AverageCalculator {
double total = 0;
int count = 0;
public:
void operator()(double value) {
total += value;
++count;
}
double getAverage() const {
return count ? total/count : 0;
}
};
vector<double> data {1.5, 2.5, 3.5, 4.5};
AverageCalculator calc = for_each(data.begin(), data.end(), AverageCalculator());
cout << "Average: " << calc.getAverage(); // 输出3.0
3.2 模板化函数对象
cpp复制template<typename T>
class Clamp {
T minVal, maxVal;
public:
Clamp(T min, T max) : minVal(min), maxVal(max) {}
T operator()(T value) const {
return std::clamp(value, minVal, maxVal);
}
};
vector<int> values {10,5,8,15,3};
Clamp<int> clamp5to10(5,10);
transform(values.begin(), values.end(), values.begin(), clamp5to10);
// values变为 {10,5,8,10,5}
3.3 函数对象组合
通过组合现有函数对象创建新操作:
cpp复制template<typename F1, typename F2>
class ComposedOp {
F1 f1;
F2 f2;
public:
ComposedOp(F1 f1, F2 f2) : f1(f1), f2(f2) {}
auto operator()(auto x) const {
return f2(f1(x));
}
};
auto square = [](int x) { return x*x; };
auto increment = [](int x) { return x+1; };
ComposedOp<decltype(square), decltype(increment)> squareThenIncrement(square, increment);
cout << squareThenIncrement(3); // 输出10 (3²+1)
4. 现代C++中的演进与最佳实践
4.1 lambda表达式的崛起
C++11引入的lambda本质上是匿名函数对象的语法糖:
cpp复制auto compareLength = [](const string& a, const string& b) {
return a.length() < b.length();
};
vector<string> words {"apple", "banana", "cherry"};
sort(words.begin(), words.end(), compareLength);
4.2 通用lambda(C++14)
cpp复制auto genericAdd = [](auto a, auto b) { return a + b; };
cout << genericAdd(3,5) << genericAdd(1.5,2.5); // 输出8和4.0
4.3 捕获列表的高级用法
cpp复制double factor = 1.5;
auto scale = [factor](auto x) { return x * factor; };
vector<double> values {1.0,2.0,3.0};
transform(values.begin(), values.end(), values.begin(), scale);
// values变为 {1.5,3.0,4.5}
4.4 性能考量与内联优化
函数对象相比函数指针的优势在于编译器更容易内联优化:
cpp复制// 函数指针 - 可能无法内联
void (*fp)(int) = [](int x) { cout << x; };
fp(42);
// 函数对象 - 几乎总能内联
auto fo = [](int x) { cout << x; };
fo(42);
实测建议:在性能敏感场景,优先使用lambda而非std::function,后者有类型擦除开销。
5. 实战:构建灵活的策略系统
5.1 策略模式实现
cpp复制template<typename T>
class SortingStrategy {
public:
virtual void sort(vector<T>&) const = 0;
};
template<typename T>
class QuickSort : public SortingStrategy<T> {
public:
void sort(vector<T>& v) const override {
std::sort(v.begin(), v.end());
}
};
template<typename T>
class CustomSort {
function<bool(T,T)> comp;
public:
CustomSort(function<bool(T,T)> c) : comp(c) {}
void operator()(vector<T>& v) const {
std::sort(v.begin(), v.end(), comp);
}
};
vector<int> data {5,3,8,1,4};
CustomSort<int> cs([](int a, int b) { return a > b; });
cs(data); // 降序排列
5.2 基于策略的算法选择
cpp复制class DataProcessor {
function<void(vector<int>&)> process;
public:
explicit DataProcessor(function<void(vector<int>&)> p) : process(p) {}
void execute(vector<int>& data) {
auto start = chrono::high_resolution_clock::now();
process(data);
auto end = chrono::high_resolution_clock::now();
cout << "耗时: "
<< chrono::duration_cast<chrono::microseconds>(end-start).count()
<< "μs\n";
}
};
vector<int> bigData(1000000);
iota(bigData.begin(), bigData.end(), 0);
DataProcessor dp1([](vector<int>& v) { sort(v.begin(), v.end()); });
DataProcessor dp2([](vector<int>& v) { stable_sort(v.begin(), v.end()); });
dp1.execute(bigData); // 测试普通排序
dp2.execute(bigData); // 测试稳定排序
5.3 组合策略实现复杂逻辑
cpp复制class Pipeline {
vector<function<void(vector<int>&)>> stages;
public:
template<typename F>
void addStage(F&& f) {
stages.emplace_back(forward<F>(f));
}
void execute(vector<int>& data) {
for(auto& stage : stages) {
stage(data);
}
}
};
vector<int> data {5,2,8,1,6,3};
Pipeline pipeline;
pipeline.addStage([](vector<int>& v) { sort(v.begin(), v.end()); });
pipeline.addStage([](vector<int>& v) {
v.erase(remove_if(v.begin(), v.end(), [](int x) { return x%2==0; }), v.end());
});
pipeline.execute(data); // 先排序再移除偶数
6. 常见陷阱与优化技巧
6.1 对象生命周期问题
cpp复制function<void()> createCallback() {
int localVar = 42;
return [&localVar]() { cout << localVar; }; // 危险!悬垂引用
}
auto badCallback = createCallback();
badCallback(); // 未定义行为
解决方案:
cpp复制// 按值捕获
return [localVar]() { cout << localVar; };
// 或者使用shared_ptr
auto sharedVar = make_shared<int>(42);
return [sharedVar]() { cout << *sharedVar; };
6.2 性能热点分析
cpp复制vector<int> data(1000000);
// 测试lambda性能
auto start = chrono::high_resolution_clock::now();
sort(data.begin(), data.end(), [](int a, int b) {
return a < b;
});
auto end = chrono::high_resolution_clock::now();
实测发现:对于简单比较器,函数对象比std::function快2-3倍
6.3 多线程注意事项
cpp复制mutex mtx;
vector<int> sharedData;
auto unsafeOp = [&](int i) {
mtx.lock();
sharedData.push_back(i);
mtx.unlock(); // 异常安全?
};
// 更安全的RAII方式
auto safeOp = [&](int i) {
lock_guard<mutex> lock(mtx);
sharedData.push_back(i);
};
6.4 调试技巧
使用typeid检查可调用对象类型:
cpp复制auto lambda = [](){};
cout << typeid(lambda).name() << endl;
function<void()> f = lambda;
cout << typeid(f).name() << endl;
使用gdb调试lambda:
code复制break filename.cpp:行号 # 在lambda定义行设置断点
7. 扩展应用:实现领域特定语言(DSL)
7.1 流畅接口设计
cpp复制class QueryBuilder {
string query;
public:
QueryBuilder& select(const string& fields) {
query += "SELECT " + fields + " ";
return *this;
}
QueryBuilder& from(const string& table) {
query += "FROM " + table + " ";
return *this;
}
QueryBuilder& where(const string& condition) {
query += "WHERE " + condition;
return *this;
}
string build() const { return query; }
};
auto query = QueryBuilder()
.select("name, age")
.from("users")
.where("age > 18")
.build();
7.2 表达式模板
cpp复制template<typename L, typename R>
class AddExpr {
const L& lhs;
const R& rhs;
public:
AddExpr(const L& l, const R& r) : lhs(l), rhs(r) {}
auto operator[](size_t i) const { return lhs[i] + rhs[i]; }
};
class Vector {
vector<double> data;
public:
Vector(size_t size) : data(size) {}
double& operator[](size_t i) { return data[i]; }
double operator[](size_t i) const { return data[i]; }
template<typename Expr>
Vector& operator=(const Expr& expr) {
for(size_t i=0; i<data.size(); ++i) {
data[i] = expr[i];
}
return *this;
}
};
Vector a(3), b(3), c(3);
a[0]=1; a[1]=2; a[2]=3;
b[0]=4; b[1]=5; b[2]=6;
c = AddExpr<Vector,Vector>(a,b); // 延迟计算
7.3 规则引擎实现
cpp复制class RuleEngine {
vector<function<bool()>> rules;
public:
template<typename F>
void addRule(F&& rule) {
rules.emplace_back(forward<F>(rule));
}
void run() {
for(auto& rule : rules) {
if(!rule()) {
throw runtime_error("规则验证失败");
}
}
}
};
RuleEngine engine;
int balance = 5000;
engine.addRule([&]() { return balance >= 0; });
engine.addRule([&]() { return balance < 10000; });
try {
engine.run();
} catch(const exception& e) {
cerr << e.what() << endl;
}
8. 跨语言对比与设计启示
8.1 与Python装饰器比较
C++函数适配器类似于Python装饰器:
python复制# Python装饰器
def log_call(func):
def wrapper(*args, **kwargs):
print(f"Calling {func.__name__}")
return func(*args, **kwargs)
return wrapper
@log_call
def greet(name):
print(f"Hello {name}")
等效C++实现:
cpp复制template<typename F>
class LogCall {
F f;
public:
LogCall(F&& f) : forward<F>(f) {}
template<typename... Args>
auto operator()(Args&&... args) {
cout << "Calling function\n";
return f(forward<Args>(args)...);
}
};
auto greet = LogCall([](const string& name) {
cout << "Hello " << name << endl;
});
greet("World");
8.2 与Java函数式接口对比
Java的函数式接口(如Predicate, Function)与C++的函数对象概念类似:
java复制// Java
Predicate<String> isLong = s -> s.length() > 5;
Function<String, Integer> length = String::length;
等效C++实现:
cpp复制// C++
auto isLong = [](const string& s) { return s.length() > 5; };
function<size_t(const string&)> length = &string::length;
8.3 设计模式启示
函数对象和适配器实现了多种设计模式:
- 策略模式:通过不同的函数对象实现算法替换
- 装饰器模式:适配器可以层层包装函数对象
- 命令模式:函数对象封装了操作和参数
- 访问者模式:通过函数对象实现双重分发
cpp复制// 访问者模式示例
class Circle;
class Square;
class ShapeVisitor {
public:
virtual void visit(Circle&) = 0;
virtual void visit(Square&) = 0;
};
class DrawVisitor : public ShapeVisitor {
public:
void visit(Circle&) override { cout << "Drawing circle\n"; }
void visit(Square&) override { cout << "Drawing square\n"; }
};
class Shape {
public:
virtual void accept(ShapeVisitor& v) = 0;
};
9. 性能优化深度剖析
9.1 内联与小函数优化
函数对象相比函数指针的最大优势在于内联可能性:
cpp复制// 函数指针 - 通常无法内联
void sortWithFP(vector<int>& v, bool (*cmp)(int,int)) {
sort(v.begin(), v.end(), cmp);
}
// 函数对象模板 - 可以内联
template<typename Cmp>
void sortWithFO(vector<int>& v, Cmp cmp) {
sort(v.begin(), v.end(), cmp);
}
9.2 避免std::function的类型擦除
std::function的灵活性和类型擦除带来的开销:
cpp复制function<bool(int,int)> cmp1 = less<int>{}; // 类型擦除
auto cmp2 = less<int>{}; // 保留具体类型
// cmp2比cmp1调用快2-3倍
9.3 内存访问模式优化
cpp复制vector<Data> dataset(1000000);
// 不好的方式:每次比较都访问多个成员
sort(dataset.begin(), dataset.end(), [](const Data& a, const Data& b) {
return a.value1 < b.value1 && a.value2 < b.value2;
});
// 优化方式:预计算比较键
vector<pair<int,int>> keys;
transform(dataset.begin(), dataset.end(), back_inserter(keys),
[](const Data& d) { return make_pair(d.value1, d.value2); });
// 排序键而非数据
sort(keys.begin(), keys.end());
9.4 并行算法加速
cpp复制vector<int> data(10000000);
iota(data.begin(), data.end(), 0);
// 顺序排序
auto start = chrono::high_resolution_clock::now();
sort(data.begin(), data.end());
auto end = chrono::high_resolution_clock::now();
// 并行排序
auto pstart = chrono::high_resolution_clock::now();
sort(execution::par, data.begin(), data.end());
auto pend = chrono::high_resolution_clock::now();
实测结果:在16核机器上,并行版本比顺序版本快6-8倍
10. 现代C++20/23新特性展望
10.1 概念约束的函数对象
cpp复制template<typename F>
concept Comparator = requires(F f, int a, int b) {
{ f(a,b) } -> convertible_to<bool>;
};
template<Comparator F>
void sortWithConcept(vector<int>& v, F cmp) {
sort(v.begin(), v.end(), cmp);
}
10.2 模式匹配与函数组合
C++23可能引入的模式匹配:
cpp复制auto matchExample = [](auto&& val) -> int {
inspect(val) {
[x, y] is pair => return x + y;
s is string => return s.size();
i is int => return i * 2;
_ => return 0;
}
};
10.3 协程与异步函数对象
cpp复制generator<int> range(int start, int end) {
for(int i=start; i<end; ++i)
co_yield i;
}
auto r = range(1,10);
for(int i : r) cout << i << " ";
10.4 元编程与编译期函数对象
cpp复制constexpr auto compileTimeSquare = [](int x) {
return x * x;
};
static_assert(compileTimeSquare(5) == 25);
11. 工程实践建议
11.1 API设计准则
-
优先模板参数:设计接受可调用对象的API时,使用模板参数而非
std::functioncpp复制// 推荐 template<typename F> void applyOperation(F&& f); // 不推荐 void applyOperation(function<void()> f); -
完美转发:保持可调用对象的值类别
cpp复制template<typename F> void wrapper(F&& f) { forward<F>(f)(); // 保持左值/右值性质 } -
约束概念:C++20起使用concept约束可调用对象
cpp复制template<typename F> concept Predicate = requires(F f, int x) { { f(x) } -> convertible_to<bool>; };
11.2 测试策略
-
单元测试函数对象
cpp复制TEST(MyFunctionObjectTest, HandlesPositiveInput) { MyFunctionObject func; EXPECT_EQ(42, func(40)); } -
测试适配器组合
cpp复制TEST(AdapterCompositionTest, CorrectlyChainsOperations) { auto adapted = compose(adapter1, adapter2); EXPECT_EQ("expected", adapted("input")); } -
性能基准测试
cpp复制BENCHMARK("Lambda vs Function", [](benchmark::State& state) { auto lambda = [](int x) { return x*x; }; function<int(int)> func = lambda; for(auto _ : state) { benchmark::DoNotOptimize(lambda(42)); benchmark::DoNotOptimize(func(42)); } });
11.3 调试与维护
-
类型打印技巧
cpp复制template<typename F> void debugFunctionType(F&& f) { using type = decay_t<F>; cout << typeid(type).name() << endl; } -
日志装饰器
cpp复制template<typename F> auto makeLogged(F&& f, string_view name) { return [f=forward<F>(f), name](auto&&... args) { cout << "Calling " << name << "\n"; return f(forward<decltype(args)>(args)...); }; } -
异常处理包装
cpp复制template<typename F> auto makeSafe(F&& f) { return [f=forward<F>(f)](auto&&... args) noexcept { try { return f(forward<decltype(args)>(args)...); } catch(...) { cerr << "Exception caught in function wrapper\n"; return decltype(f(args...)){}; } }; }
12. 典型案例分析:STL算法改造
12.1 增强版find_if
cpp复制template<typename It, typename Pred, typename Action>
It find_if_do(It first, It last, Pred pred, Action action) {
It it = find_if(first, last, pred);
if(it != last) action(*it);
return it;
}
vector<int> v {1,3,5,7,9};
find_if_do(v.begin(), v.end(),
[](int x) { return x > 5; },
[](int x) { cout << "Found: " << x << endl; }
);
12.2 可中断for_each
cpp复制template<typename It, typename F>
bool interruptible_for_each(It first, It last, F f) {
for(; first != last; ++first) {
if(!f(*first)) return false;
}
return true;
}
vector<int> data {1,2,3,4,5};
interruptible_for_each(data.begin(), data.end(), [](int x) {
cout << x << endl;
return x < 3; // 遇到3时停止
});
12.3 带进度的transform
cpp复制template<typename It1, typename It2, typename F>
It2 transform_with_progress(It1 first1, It1 last1, It2 first2, F f,
function<void(size_t)> progress) {
size_t total = distance(first1, last1);
size_t done = 0;
It2 result = first2;
for(; first1 != last1; ++first1, ++result) {
*result = f(*first1);
progress(++done * 100 / total);
}
return result;
}
vector<int> src(1000), dest(1000);
iota(src.begin(), src.end(), 0);
transform_with_progress(src.begin(), src.end(), dest.begin(),
[](int x) { return x*x; },
[](size_t p) { cout << "\r" << p << "%"; flush(cout); }
);
13. 高级模式:类型擦除与多态函数
13.1 自定义类型擦除容器
cpp复制class AnyCallable {
struct Concept {
virtual ~Concept() = default;
virtual void invoke() = 0;
};
template<typename F>
struct Model : Concept {
F f;
Model(F f) : f(f) {}
void invoke() override { f(); }
};
unique_ptr<Concept> impl;
public:
template<typename F>
AnyCallable(F&& f) : impl(new Model<decay_t<F>>(forward<F>(f))) {}
void operator()() { impl->invoke(); }
};
AnyCallable ac1([]{ cout << "Hello\n"; });
AnyCallable ac2(bind(printSum, 3, 5));
ac1(); // 输出Hello
ac2(); // 输出8
13.2 多态函数包装器
cpp复制template<typename... Args>
class PolymorphicFunction {
struct Concept {
virtual ~Concept() = default;
virtual void operator()(Args...) = 0;
};
template<typename F>
struct Model : Concept {
F f;
Model(F f) : f(f) {}
void operator()(Args... args) override { f(args...); }
};
unique_ptr<Concept> impl;
public:
template<typename F>
PolymorphicFunction(F&& f) : impl(new Model<decay_t<F>>(forward<F>(f))) {}
void operator()(Args... args) { (*impl)(args...); }
};
PolymorphicFunction<int,int> pf([](int a, int b) { cout << a + b; });
pf(3,5); // 输出8
13.3 小型缓冲区优化
cpp复制template<typename Sig, size_t BufferSize = 64>
class OptimizedFunction;
template<typename R, typename... Args, size_t BufferSize>
class OptimizedFunction<R(Args...), BufferSize> {
alignas(max_align_t) char buffer[BufferSize];
R (*invoke)(void*, Args...) = nullptr;
void (*destroy)(void*) = nullptr;
template<typename F>
static R invokeFunc(void* f, Args... args) {
return (*static_cast<F*>(f))(args...);
}
template<typename F>
static void destroyFunc(void* f) {
static_cast<F*>(f)->~F();
}
public:
template<typename F>
OptimizedFunction(F&& f) {
static_assert(sizeof(F) <= BufferSize, "Type too large");
new(buffer) decay_t<F>(forward<F>(f));
invoke = &invokeFunc<decay_t<F>>;
destroy = &destroyFunc<decay_t<F>>;
}
R operator()(Args... args) {
return invoke(buffer, args...);
}
~OptimizedFunction() {
if(destroy) destroy(buffer);
}
};
OptimizedFunction<int(int)> of([](int x) { return x*x; });
cout << of(5); // 输出25
14. 元编程与编译期函数对象
14.1 constexpr函数对象
cpp复制struct Square {
constexpr int operator()(int x) const { return x*x; }
};
constexpr int result = Square{}(5); // 编译期计算
static_assert(result == 25);
14.2 类型生成器模式
cpp复制template<typename T>
struct ComparatorGenerator {
using type = function<bool(const T&, const T&)>;
static type make_less() {
return [](const T& a, const T& b) { return a < b; };
}
static type make_greater() {
return [](const T& a, const T& b) { return a > b; };
}
};
auto strComp = ComparatorGenerator<string>::make_greater();
vector<string> words {"apple", "banana"};
sort(words.begin(), words.end(), strComp);
14.3 策略选择器
cpp复制template<size_t N>
struct AlgorithmSelector {
auto getAlgorithm() const {
if constexpr(N == 1) return [](auto x) { return x*x; };
else if constexpr(N == 2) return [](auto x) { return x+x; };
else return [](auto x) { return x; };
}
};
constexpr auto algo = AlgorithmSelector<1>{}.getAlgorithm();
cout << algo(5); // 输出25
15. 跨领域应用案例
15.1 GUI事件处理
cpp复制class Button {
vector<function<void()>> clickHandlers;
public:
void addClickHandler(function<void()> handler) {
clickHandlers.push_back(move(handler));
}
void click() {
for(auto& handler : clickHandlers) {
handler();
}
}
};
Button btn;
btn.addClickHandler([] { cout << "Hello\n"; });
btn.addClickHandler(bind(printSum, 3, 5));
btn.click(); // 输出Hello和8
15.2 游戏AI行为树
cpp复制class BehaviorNode {
function<bool()> action;
public:
BehaviorNode(function<bool()> a) : action(move(a)) {}
bool execute() { return action(); }
};
BehaviorNode attack([] {
cout << "Attacking enemy\n";
return true;
});
BehaviorNode flee([] {
cout << "Fleeing from danger\n";
return true;
});
// 根据条件选择行为
auto aiBehavior = [&](bool isStrong) {
return isStrong ? attack.execute() : flee.execute();
};
15.3 金融交易策略
cpp复制class TradingStrategy {
function<bool(double,double)> buyCondition;
function<bool(double,double)> sellCondition;
public:
template<typename Buy, typename Sell>
TradingStrategy(Buy&& buy, Sell&& sell)
: buyCondition(forward<Buy>(buy)),
sellCondition(forward<Sell>(sell)) {}
void execute(double price, double indicator) {
if(buyCondition(price, indicator)) {
cout << "Buy signal\n";
} else if(sellCondition(price, indicator)) {
cout << "Sell signal\n";
}
}
};
TradingStrategy strategy(
[](double p, double i) { return p < 100 && i > 0.5; }, // 买入条件
[](double p, double i) { return p > 150 || i < -0.5; } // 卖出条件
);
strategy.execute(90, 0.6); // 输出Buy signal
16. 测试与调试专项
16.1 函数对象单元测试
cpp复制TEST(FunctionObjectTest, SquareOperation) {
Square square;
EXPECT_EQ(16, square(4));
auto lambdaSquare = [](int x) { return x*x; };
EXPECT_EQ(25, lambdaSquare(5));
}
TEST(AdapterTest, BindReordersParameters) {
auto reversed = bind(printSum, _2, _1);
testing::internal::CaptureStdout();
reversed(3,5);
string output = testing::internal::GetCapturedStdout();
EXPECT_EQ("8", output);
}
16.2 性能剖析方法
cpp复制void profileFunctionObjects() {
const size_t N = 1000000;
vector<int> data(N);
iota(data.begin(), data.end(), 0);
auto start = chrono::high_resolution_clock::now();
sort(data.begin(), data.end(), greater<int>());
auto end = chrono::high_resolution_clock::now();
cout << "Function object: "
<< chrono::duration_cast<chrono::microseconds>(end-start).count()
<< "μs\n";
start = chrono::high_resolution_clock::now();
sort(data.begin(), data.end(), [](int a, int b) { return a > b; });
end = chrono::high_resolution_clock::now();
cout << "Lambda: "
<< chrono::duration_cast<chrono::microseconds>(end-start).count()
<< "μs\n";
}
16.3 代码覆盖率分析
使用gcov和lcov工具分析测试覆盖率:
bash复制g++ -std=c++20 -fprofile-arcs -ftest-coverage -O0 test.cpp
./a.out
lcov --capture --directory . --output-file coverage.info
genhtml coverage.info --output-directory coverage-report
16.4 静态分析检查
使用clang-tidy进行静态分析:
bash复制clang-tidy test.cpp --checks=modernize-*,performance-* -- -std=c++20
常见检查项:
- modernize-use-nodiscard
- performance-unnecessary-value-param
- performance-for-range-copy
- modernize-avoid-bind
17. 设计模式深度集成
17.1 命令模式实现
cpp复制class Command {
public:
virtual ~Command() = default;
virtual void execute() = 0;
};
template<typename F>
class FunctionCommand : public Command {
F f;
public:
FunctionCommand(F&& f) : f(forward<F>(f)) {}
void execute() override { f(); }
};
template<typename F>
auto make_command(F&& f) {
return make_unique<FunctionCommand<decay_t<F>>>(forward<F>(f));
}
vector<unique_ptr<Command>> commands;
commands.push_back(make_command([] { cout << "Command 1\n"; }));
commands.push_back(make_command(bind(printSum, 3, 5)));
for(auto& cmd : commands) {
cmd->execute();
}
17.2 观察者模式实现
cpp复制class Observable {
vector<function<void(int)>> observers;
public:
void addObserver(function<void(int)> obs) {
observers.push_back(move(obs));
}
void notify(int value) {
for(auto& obs : observers) {
obs(value