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

c++链式调用

        链式调用(Chaining)是一种设计方法,它允许你通过一个对象的多个方法连续调用,而不需要在每次调用后重新引用对象。这种方法在构建复杂对象时尤其有用,特别是在使用建造者模式时。

        在C++中,实现链式调用的常见方法是让每个方法返回对象本身的引用(通常是 *this)。这样,调用者就可以在同一个表达式中继续调用其他方法。

示例:链式调用在C++中的实现

        下面是一个简单的示例,展示如何在C++中使用链式调用来设置一个类的属性。

 示例:设置一个简单的 Person 类

#include <iostream>
#include <string>

class Person {
public:
    Person& setName(const std::string& name) {
        this->name = name;
        return *this;
    }

    Person& setAge(int age) {
        this->age = age;
        return *this;
    }

    Person& setAddress(const std::string& address) {
        this->address = address;
        return *this;
    }

    void display() const {
        std::cout << "Name: " << name << ", Age: " << age << ", Address: " << address << std::endl;
    }

private:
    std::string name;
    int age;
    std::string address;
};

int main() {
    Person person;
    person.setName("John Doe").setAge(30).setAddress("123 Main St").display();

    return 0;
}

        在这个示例中,Person 类的每个 setter 方法都返回对当前对象的引用(*this),允许我们链式调用这些方法。display 方法用于显示对象的属性。

结合建造者模式和链式调用

        链式调用在建造者模式中也非常有用,特别是当你需要构建复杂对象时。下面是一个结合建造者模式和链式调用的示例:

示例:建造者模式与链式调用

#include <iostream>
#include <string>

class Product {
public:
    void show() const {
        std::cout << "Product [PartA: " << partA << ", PartB: " << partB << ", PartC: " << partC << "]" << std::endl;
    }

    // 友元类 Builder 以便能访问 Product 的私有成员
    friend class Builder;

private:
    std::string partA;
    std::string partB;
    std::string partC;
};

class Builder {
public:
    Builder& buildPartA(const std::string& partA) {
        product.partA = partA;
        return *this;
    }

    Builder& buildPartB(const std::string& partB) {
        product.partB = partB;
        return *this;
    }

    Builder& buildPartC(const std::string& partC) {
        product.partC = partC;
        return *this;
    }

    Product getResult() {
        return product;
    }

private:
    Product product;
};

int main() {
    Builder builder;
    Product product = builder.buildPartA("PartA1").buildPartB("PartB1").buildPartC("PartC1").getResult();
    product.show();

    return 0;
}

        在这个示例中,Builder 类的每个方法都返回 *this,使得我们可以链式调用这些方法来逐步构建 Product 对象。最终的 getResult 方法返回构建的 Product 对象。

        在C++中,*this 返回的是当前对象的引用。为了更具体地解释,让我们看一下 *this 是如何工作的。

*this 的含义

        this 是一个指针,它指向调用成员函数的对象。*this 则是对这个对象的解引用,因而得到的是该对象本身。因此,当你在成员函数中返回 *this 时,实际上是返回调用该函数的对象自身的引用。

示例:解释 *this

        让我们通过一个简单的例子来解释它的工作原理。

#include <iostream>
#include <string>

class Person {
public:
    Person& setName(const std::string& name) {
        this->name = name;  // 使用 this 指针访问成员变量
        return *this;       // 返回对象本身的引用
    }

    void display() const {
        std::cout << "Name: " << name << std::endl;
    }

private:
    std::string name;
};

int main() {
    Person person;
    person.setName("John Doe").display();
    return 0;
}

        在这个例子中,Person 类有一个 setName 方法,该方法接受一个字符串参数并设置对象的 name 属性。然后,该方法返回 *this,即当前对象的引用。这使得你可以链式调用 display() 方法。

详细解读

  1. person.setName("John Doe"):当你调用 setName 方法时,this 指针指向 person 对象。
  2. this->name = name:使用 this 指针修改对象的成员变量。
  3. return *this:返回当前对象的引用,即 person 对象的引用。
  4. .display():由于 setName 返回的是 person 对象的引用,你可以继续调用 display 方法。

对象的生命周期

        需要注意的是,返回 *this 时,返回的是对象的引用,而不是对象的副本,这意味着你在链式调用中操作的是同一个对象。例如:

        Person& p = person.setName("Jane Doe");

        在这个语句中,p 是对 person 对象的引用,而不是一个新的对象。任何对 p 的操作实际上都是对 person 的操作。

        *this 返回的是调用成员函数的对象自身的引用。这使得链式调用成为可能,因为每个函数调用都返回相同的对象,可以继续调用其他成员函数。这种设计模式在需要设置或修改多个属性时特别有用,从而使代码更简洁和易读。

下面是进一步针对创建者模式,讲解*this 指针

示例:Builder 模式与链式调用

#include <iostream>
#include <string>

class Product {
public:
    void show() const {
        std::cout << "Product [PartA: " << partA << ", PartB: " << partB << ", PartC: " << partC << "]" << std::endl;
    }

    // 友元类 Builder 以便能访问 Product 的私有成员
    friend class Builder;

private:
    std::string partA;
    std::string partB;
    std::string partC;
};

class Builder {
public:
    Builder& buildPartA(const std::string& partA) {
        product.partA = partA;
        return *this;
    }

    Builder& buildPartB(const std::string& partB) {
        product.partB = partB;
        return *this;
    }

    Builder& buildPartC(const std::string& partC) {
        product.partC = partC;
        return *this;
    }

    Product getResult() {
        return product;
    }

private:
    Product product;
};

int main() {
    Builder builder;
    Product product = builder.buildPartA("PartA1").buildPartB("PartB1").buildPartC("PartC1").getResult();
    product.show();

    return 0;
}

详细解读

Builder 类中的方法

        buildPartA, buildPartB, 和 buildPartC 方法在 Builder 类中被定义。这些方法修改 Builder 类的成员变量 product,并且每个方法都返回 *this,即 Builder 的引用。

        这使得我们可以链式调用这些方法,例如:

        builder.buildPartA("PartA1").buildPartB("PartB1").buildPartC("PartC1")。

product 成员变量

        Builder 类有一个私有成员变量 product,它是一个 Product 对象。每个 buildPartX 方法都会修改这个 Product 对象的相应部分。

返回 Builder 对象的引用

        每个 buildPartX 方法返回 *this,即当前 Builder 对象的引用。这使得我们可以链式调用这些方法,从而逐步构建 Product 对象。

最终生成 Product 对象

        最后,通过调用 getResult() 方法,返回 product 对象。此时,product 对象已经通过之前的链式调用被完全构建好。

为什么 Builder 调用写进了 Product 内

  • Builder 类的作用是逐步构建 Product 对象。每次调用 buildPartX 方法时,都是在修改 Builder 类内部的 Product 对象,而不是创建新的 Builder 或 Product 对象。
  • 最终,通过调用 getResult() 方法,返回构建好的 Product 对象。

        在 Builder 模式中,链式调用的返回值是 Builder 对象的引用(*this),这使得我们可以连续调用 Builder 类的方法来设置 Product 对象的属性。Builder 内部持有一个 Product 对象,并在链式调用中逐步构建这个对象。最终,通过 getResult() 方法返回构建好的 Product 对象。


http://www.kler.cn/news/354454.html

相关文章:

  • 【css-在一个元素中设置font-size和实际渲染字体大小不一致】
  • CAT(Card Application Toolkit)- LSI
  • Jenkins整合Docker实现CICD自动化部署(若依项目)
  • ESP32-IDF USART 专题
  • 如何在Android中进行日志打印和调试?
  • 即时通讯增加kafka渠道
  • 基于workbox实现PWA预缓存能力
  • 11.9K Star!强大的 Web 爬虫工具 FireCrawl:为 AI 训练与数据提取提供全面支持
  • 【Linux】解读信号的本质&相关函数及指令的介绍
  • UI自动化测试 —— web端元素获取元素等待实践!
  • 国产游戏技术:迈向全球引领者的征途
  • 2.计算机网络_IP地址
  • React 探秘(一):fiber 架构
  • 自动驾驶系列—探索自动驾驶持续部署(CD)技术与最佳实践
  • UE5 猎户座漂浮小岛 01 资源 玩家角色
  • 从2.x到3.x:Spring Boot升级实战踩坑记录!
  • Go语言中的时间比较与时区处理
  • 利用Microsoft Entra Application Proxy在无公网IP条件下安全访问内网计算机
  • 代码训练营 day34|LeetCode 134,LeetCode 135,LeetCode 860,LeetCode 406
  • 根据Vue对比来深入学习React 下 props 组件传值 插槽 样式操作 hooks 高阶组件 性能优化