当前位置: 首页 > article >正文

C++中的链式操作原理与应用(一)

目录

1.引言

2.原理

3.方法的正确声明

4.与设计模式的应用

4.1.流式接口(Fluent Interface)

4.2.与建造者模式的结合

5.实例分享

5.1.iostream库

5.2.jQuery(JavaScript库)

6.总结


1.引言

        在C++中,链式操作(也称为“链式调用”或“流式接口”)是一种设计模式,允许你在单个表达式中对一个对象的多个成员函数进行连续调用。每个成员函数都会返回对象本身(通常是 *this 或 this 指针),这样你就可以在同一个表达式中继续调用下一个成员函数。

        它的特点是在一条语句中出现两个或者两个以上相同的操作符,如连续的赋值操作、连续的输入操作、连续的输出操作、连续的相加操作等都是链式操作的样例。

        链式操作一定涉及到结合律的问题。比如链式操作赋值操作满足右结合律,即a=b=c被解释成a=(b=c)。而链式输出操作原则满足左结合律,即cout<<a<<b被解释成(cout<<a)<<b,基本数据类型的链式操作都有明白的定义。而涉及到类类型的链式操作则往往须要进行对应操作符的重载。

        链式操作通常用于简化代码,使代码更简洁和易读。这种技术常见于需要设置多个选项或属性的场景,例如配置对象或进行一系列操作。

2.原理

1)运算符重载
  a.为了实现类类型的链式操作,通常需要对相关的运算符进行重载。
  b.运算符重载函数不能返回void类型,因为void类型不能参与任何运算,从而无法支持链式操作。
  c.常见的需要重载的运算符包括赋值运算符(=)、输入运算符(>>)和输出运算符(<<)等。
2)返回对象自身或其引用
   a.运算符重载函数需要返回对象自身或其引用,以便能够继续在该对象上执行其他操作。
   b.对于赋值运算符重载,通常返回对象的引用(例如 *this),以避免不必要的拷贝构造函数调用,提高程序效率。
   c.对于输入和输出运算符重载,也需要返回相应的流对象的引用(例如 istream& 或 ostream&),以支持链式输入输出操作。

以下是一个简单的示例,展示了如何通过运算符重载实现链式操作:

#include <iostream>
#include <string>

class ChainExample {
private:
    int value;
    std::string text;

public:
    ChainExample& setValue(int v) {
        value = v;
        return *this;  // 返回当前对象的引用,支持链式操作
    }

    ChainExample& setText(const std::string& t) {
        text = t;
        return *this;  // 返回当前对象的引用,支持链式操作
    }

    void print() const {
        std::cout << "Value: " << value << ", Text: " << text << std::endl;
    }
};

int main() {
    ChainExample example;
    example.setValue(42).setText("Hello, World!").print();  // 链式操作示例

    return 0;
}

在这个示例中,ChainExample 类有两个成员函数 setValue 和 setText,它们都返回当前对象的引用,从而支持链式操作。在 main 函数中,我们通过链式操作设置了对象的属性并打印了它们。

3.方法的正确声明

1) 非 const 方法:如果方法会修改对象的状态,则应声明为非 const 方法,返回 MyClass&

MyClass& setValue(int val) { value = val; return *this; }

2) const 方法:如果方法不修改对象的状态,可以声明为 const 方法,返回 const MyClass&

const MyClass& display() const { // ... 显示操作 return *this; }

4.与设计模式的应用

  • 建造者(Builder Pattern):通过链式调用逐步构建复杂对象。
  • 流式接口(Fluent Interface):提供一种更加自然、易读的 API 设计方式,常用于领域特定语言(DSL)的实现。

4.1.流式接口(Fluent Interface)

流式接口是一种创建对象的方法链,旨在提高代码的可读性和流畅性。其核心思想是通过链式调用,使代码看起来像自然语言描述。

class QueryBuilder {
public:
    QueryBuilder& select(const std::string& fields) {
        query += "SELECT " + fields + " ";
        return *this;
    }

    QueryBuilder& from(const std::string& table) {
        query += "FROM " + table + " ";
        return *this;
    }

    QueryBuilder& where(const std::string& condition) {
        query += "WHERE " + condition + " ";
        return *this;
    }

    std::string build() const {
        return query;
    }

private:
    std::string query;
};

调用方式

QueryBuilder qb;
std::string sql = qb.select("*").from("users").where("age > 30").build();

4.2.与建造者模式的结合

建造者模式(Builder Pattern) 常与流式接口结合使用,用于构建复杂对象。如:

class Product {
public:
    // Product 的属性和方法
};

class ProductBuilder {
public:
    ProductBuilder& setPartA(int value) {
        // 设置 PartA
        return *this;
    }

    ProductBuilder& setPartB(const std::string& value) {
        // 设置 PartB
        return *this;
    }

    Product build() {
        return product;
    }

private:
    Product product;
};

调用方式:

Product product = ProductBuilder().setPartA(10).setPartB("example").build();

5.实例分享

5.1.iostream库

C++中的iostream库:使用<<>>操作符进行数据的输入和输出,支持链式调用。

一般来说,实现输入操作符重载,一律采用例如以下函数原型:

istream& operator>>(istream&, className&);

而实现输出操作符重载,一律采用例如以下函数原型:

ostream& operator<<(ostream&, className&);

假设操作符函数的返回的是istream或ostream类的对象。而不是引用,会出现编译错误。

以下是一个简单的示例,展示了如何在C++中实现一个支持流式接口的自定义类:

#include <iostream>
#include <string>

class Person {
public:
    std::string name;
    int age;

    // 重载插入运算符以支持流式输出
    friend std::ostream& operator<<(std::ostream& os, const Person& p) {
        os << "Name: " << p.name << ", Age: " << p.age;
        return os; // 返回流对象的引用以支持链式操作
    }

    // 重载提取运算符以支持流式输入(可选)
    // 注意:为了简化示例,这里省略了输入验证和错误处理
    friend std::istream& operator>>(std::istream& is, Person& p) {
        is >> p.name >> p.age;
        return is; // 返回流对象的引用以支持链式操作
    }
};

int main() {
    Person p;
    std::cout << "Enter name and age: ";
    std::cin >> p; // 使用重载的提取运算符从标准输入读取数据
    std::cout << p << std::endl; // 使用重载的插入运算符将数据输出到标准输出
    return 0;
}

在这个示例中,Person类被设计为支持流式接口。我们重载了插入运算符(<<)和提取运算符(>>)来分别处理Person对象的输出和输入。这样,我们就可以使用标准的输入输出流语法来处理Person对象了。

手撕代码: C++实现数据的序列化和反序列化_c++ 序列化-CSDN博客

5.2.jQuery(JavaScript库)

用于数据库查询时,可以通过链式调用设置查询条件、执行查询并处理结果。

其他面向对象编程语言中的流式接口实现,如Java中的jOOQ库等。

6.总结

  1. 可读性:虽然链式表达式可以使代码更简洁,但过度使用可能会导致代码难以阅读和维护。
  2. 错误处理:链式调用中的错误处理可能会更加复杂,因为每个函数调用都依赖于前一个函数调用的结果。
  3. 性能:在某些情况下,链式表达式可能引入不必要的对象复制或引用开销,尽管现代C++的优化技术可以减轻这些影响。

通过合理使用链式表达式,你可以编写出更加简洁和优雅的C++代码。


http://www.kler.cn/a/411031.html

相关文章:

  • SAP 零售方案 CAR 系统的介绍与研究
  • 【案例】泛微.齐业成助力北京中远大昌汽车实现数电票全流程管理
  • 微信小程序下拉刷新与上拉触底的全面教程
  • 香港大带宽服务器:助力高效网络应用
  • SAP ME2L/ME2M/ME3M报表增强添加字段
  • Neural Magic 发布 LLM Compressor:提升大模型推理效率的新工具
  • 学习日记_20241126_聚类方法(自组织映射Self-Organizing Maps, SOM)
  • 如何使用GCC手动编译stm32程序
  • 计算机的错误计算(一百六十七)
  • JAVA题目笔记(二十)Stream流综合练习+方法引用
  • PICO 获取设备号 SN码
  • Spring Boot林业产品推荐系统:从理论到实践
  • uniapp前端开发,基于vue3,element plus组件库,以及axios通讯
  • 【消息序列】详解(7):剖析回环模式--设备测试的核心利器
  • 基于vite创建的react18项目的单元测试
  • 微服务——服务配置中心
  • 【Linux】TCP网络编程
  • 【计算机网络】核心部分复习
  • EntitasLite源码分析(一)
  • Java中的JSONObject详解
  • Day3 洛谷Day3 1161+1179+1200+1304
  • 【AI系统】昇腾 AI 架构介绍
  • 直接抄作业!Air780E模组LuatOS开发:位运算(bit)示例
  • 【MyBatis】全局配置文件—mybatis.xml 创建xml模板
  • 【设计模式】【结构型模式(Structural Patterns)】之组合模式(Composite Pattern)
  • HOW - React 状态模块化管理和按需加载(二) - jotai