C++笔记之两个类的实例之间传递参数的各种方法

C++笔记之两个类的实例之间传递参数的各种方法

code review!

文章目录

  • C++笔记之两个类的实例之间传递参数的各种方法
    • 1.构造函数参数传递
    • 2.成员函数参数传递
    • 3.友元函数
    • 4.友元类
    • 5.传递指针或引用
    • 6.静态成员变量
    • 7.静态成员函数
    • 8.全局变量或命名空间
    • 9.回调函数和函数指针
    • 10.观察者模式
    • 11.事件系统
    • 12.消息传递机制

1.构造函数参数传递

在这里插入图片描述

代码

class ClassA {
public:
    ClassA(int value) : memberA(value) {}
private:
    int memberA;
};

class ClassB {
public:
    ClassB(const ClassA& aInstance) : memberB(aInstance) {}
private:
    ClassA memberB;
};

int main() {
    ClassA objA(42);
    ClassB objB(objA);
    return 0;
}

2.成员函数参数传递

在这里插入图片描述

代码

class ClassA {
public:
    ClassA(int value) : memberA(value) {}
    int getValue() const { return memberA; }
private:
    int memberA;
};

class ClassB {
public:
    void doSomethingWithA(const ClassA& aInstance) {
        int value = aInstance.getValue();
        // 执行操作
    }
};

int main() {
    ClassA objA(42);
    ClassB objB;
    objB.doSomethingWithA(objA);
    return 0;
}

3.友元函数

在这里插入图片描述

代码

class ClassA;

class ClassB {
public:
    void printValue(const ClassA& objA);
};

class ClassA {
public:
    ClassA(int value) : aValue(value) {}

    friend void ClassB::printValue(const ClassA& objA);

private:
    int aValue;
};

void ClassB::printValue(const ClassA& objA) {
    std::cout << "Value from ClassA: " << objA.aValue << std::endl;
}

int main() {
    ClassA objA(42);
    ClassB objB;

    objB.printValue(objA);

    return 0;
}

4.友元类

在这里插入图片描述

代码

class ClassA;

class ClassB {
public:
    void printValue(const ClassA& objA);

    // Declare ClassA as a friend class
    friend class ClassA;
};

class ClassA {
public:
    ClassA(int value) : aValue(value) {}

    void setValue(int value) {
        aValue = value;
    }

private:
    int aValue;
};

void ClassB::printValue(const ClassA& objA) {
    std::cout << "Value from ClassA: " << objA.aValue << std::endl;
}

int main() {
    ClassA objA(42);
    ClassB objB;

    objB.printValue(objA);

    return 0;
}

5.传递指针或引用

在这里插入图片描述

代码

#include <iostream>

class ClassA {
public:
    ClassA(int value) : aValue(value) {}

    int getValue() const {
        return aValue;
    }

private:
    int aValue;
};

class ClassB {
public:
    void printValueByPointer(const ClassA* ptrA) {
        if (ptrA) {
            std::cout << "Value from ClassA using pointer: " << ptrA->getValue() << std::endl;
        } else {
            std::cout << "Invalid pointer to ClassA." << std::endl;
        }
    }

    void printValueByReference(const ClassA& refA) {
        std::cout << "Value from ClassA using reference: " << refA.getValue() << std::endl;
    }
};

int main() {
    ClassA objA(42);
    ClassB objB;

    // Passing pointer to ClassA
    objB.printValueByPointer(&objA); // Output: Value from ClassA using pointer: 42

    // Passing reference to ClassA
    objB.printValueByReference(objA); // Output: Value from ClassA using reference: 42

    return 0;
}

6.静态成员变量

在这里插入图片描述

代码

class ClassA {
public:
    static int sharedValue;
};

class ClassB {
public:
    void printSharedValue() {
        std::cout << "Shared Value: " << ClassA::sharedValue << std::endl;
    }
};

int ClassA::sharedValue = 42;

int main() {
    ClassB objB;
    objB.printSharedValue();

    return 0;
}

7.静态成员函数

在这里插入图片描述

代码

#include <iostream>

class SharedInfo {
public:
    static int getValue() {
        return sharedValue;
    }

    static void setValue(int value) {
        sharedValue = value;
    }

private:
    static int sharedValue;
};

// Initialize the static member
int SharedInfo::sharedValue = 0;

class ClassA {
public:
    void printSharedValue() {
        std::cout << "Shared Value from ClassA: " << SharedInfo::getValue() << std::endl;
    }
};

class ClassB {
public:
    void modifySharedValue() {
        SharedInfo::setValue(100);
    }
};

int main() {
    ClassA objA;
    ClassB objB;

    objA.printSharedValue();
    objB.modifySharedValue();
    objA.printSharedValue();

    return 0;
}

8.全局变量或命名空间

在这里插入图片描述

代码

namespace MyNamespace {
    int sharedValue = 42;
}

class ClassA {
public:
    void printSharedValue() {
        std::cout << "Shared Value: " << MyNamespace::sharedValue << std::endl;
    }
};

class ClassB {
public:
    void modifySharedValue() {
        MyNamespace::sharedValue = 100;
    }
};

int main() {
    ClassA objA;
    ClassB objB;

    objA.printSharedValue();
    objB.modifySharedValue();
    objA.printSharedValue();

    return 0;
}

9.回调函数和函数指针

在这里插入图片描述

代码

#include <iostream>

// Callback function type
typedef void (*CallbackFunction)(int);

class ClassA {
public:
    ClassA(int value) : aValue(value) {}

    void performCallback(CallbackFunction callback) {
        callback(aValue);
    }

private:
    int aValue;
};

class ClassB {
public:
    static void printValue(int value) {
        std::cout << "Value from ClassA: " << value << std::endl;
    }
};

int main() {
    ClassA objA(42);
    
    // Passing callback function using function pointer
    objA.performCallback(ClassB::printValue); // Output: Value from ClassA: 42

    return 0;
}

10.观察者模式

可以使用观察者模式在C++中在两个类的实例之间传递参数。观察者模式用于在一个对象的状态发生变化时,自动通知和更新其他相关对象。以下是一个使用观察者模式的示例,并提供运行结果:

#include <iostream>
#include <vector>

class Observer;  // Forward declaration

class Subject {
public:
    void addObserver(Observer* observer) {
        observers.push_back(observer);
    }

    void removeObserver(Observer* observer) {
        observers.erase(std::remove(observers.begin(), observers.end(), observer), observers.end());
    }

    void notify(int value) {
        for (Observer* observer : observers) {
            observer->update(value);
        }
    }

private:
    std::vector<Observer*> observers;
};

class Observer {
public:
    virtual void update(int value) = 0;
};

class ClassA : public Observer {
public:
    void attachToSubject(Subject* subject) {
        subject->addObserver(this);
    }

    void detachFromSubject(Subject* subject) {
        subject->removeObserver(this);
    }

    void update(int value) override {
        std::cout << "ClassA received update: " << value << std::endl;
    }
};

int main() {
    Subject subject;
    ClassA objA1, objA2;

    objA1.attachToSubject(&subject);
    objA2.attachToSubject(&subject);

    subject.notify(42); // Output: ClassA received update: 42 \n ClassA received update: 42

    objA1.detachFromSubject(&subject);
    subject.notify(100); // Output: ClassA received update: 100

    return 0;
}

在这个示例中,我们首先定义了一个Subject类,它维护一个观察者列表并提供添加、删除和通知观察者的功能。然后,我们定义了一个Observer类,其中包含一个抽象的update函数,用于接收主题的通知。

ClassA类继承自Observer类,实现了update函数。在main()函数中,我们创建了一个Subject对象和两个ClassA对象。然后,我们将两个ClassA对象附加到Subject对象,并调用subject.notify(42)通知观察者更新。这导致两个ClassA对象都收到了相同的更新。

接着,我们将一个ClassA对象从Subject对象分离,并再次调用subject.notify(100)。这次只有一个ClassA对象收到了更新。

运行结果将是:

ClassA received update: 42
ClassA received update: 42
ClassA received update: 100

这个例子演示了如何使用观察者模式在两个类的实例之间传递参数,其中一个类充当主题(Subject),而另一个类充当观察者(Observer)。当主题的状态发生变化时,通知所有观察者进行更新。

11.事件系统

在 C++ 中,没有内置的事件系统,但你可以模拟一个简单的事件系统来在两个类的实例之间传递参数。这可以通过函数指针、回调函数或者 C++11 中的 std::function 和 std::bind 来实现。以下是一个使用 std::function 和 std::bind 模拟事件系统的示例,并提供运行结果:

#include <iostream>
#include <functional>

class Event {
public:
    void subscribe(std::function<void(int)> callback) {
        subscribers.push_back(callback);
    }

    void unsubscribe(std::function<void(int)> callback) {
        subscribers.remove(callback);
    }

    void notify(int value) {
        for (auto& callback : subscribers) {
            callback(value);
        }
    }

private:
    std::list<std::function<void(int)>> subscribers;
};

class ClassA {
public:
    ClassA(Event* event) : event(event) {}

    void triggerEvent(int value) {
        event->notify(value);
    }

private:
    Event* event;
};

class ClassB {
public:
    void handleEvent(int value) {
        std::cout << "ClassB received event: " << value << std::endl;
    }
};

int main() {
    Event event;
    ClassA objA(&event);
    ClassB objB;

    // Subscribe ClassB's handleEvent to the event
    event.subscribe(std::bind(&ClassB::handleEvent, &objB, std::placeholders::_1));

    objA.triggerEvent(42); // Output: ClassB received event: 42

    // Unsubscribe ClassB's handleEvent from the event
    event.unsubscribe(std::bind(&ClassB::handleEvent, &objB, std::placeholders::_1));

    objA.triggerEvent(100);

    return 0;
}

在这个示例中,我们首先定义了一个简单的事件类 Event,它允许订阅者(函数)通过 subscribe 方法订阅事件,通过 unsubscribe 方法取消订阅,然后通过 notify 方法通知所有订阅者。接着,我们定义了两个类 ClassAClassBClassA 有一个触发事件的方法 triggerEvent,它会通知事件对象。ClassB 有一个处理事件的方法 handleEvent

main() 函数中,我们创建了一个 Event 对象和一个 ClassA 对象。然后,我们使用 event.subscribe 方法将 ClassB::handleEvent 方法绑定到事件上,从而订阅了事件。接着,我们调用 objA.triggerEvent(42) 来触发事件,这会导致 ClassBhandleEvent 方法被调用。

接着,我们使用 event.unsubscribe 方法取消订阅 ClassB::handleEvent 方法,然后再次调用 objA.triggerEvent(100),但因为已经取消了订阅,所以 ClassBhandleEvent 方法不会再被调用。

运行结果将是:

ClassB received event: 42

这个例子演示了如何模拟一个简单的事件系统,在两个类的实例之间传递参数。在本例中,ClassA 充当事件的触发器,ClassB 充当事件的订阅者。

12.消息传递机制

在 C++ 中,使用消息传递机制来在两个类的实例之间传递参数可以通过使用事件系统、消息队列、观察者模式等方式来实现。下面是一个使用简单的事件系统模拟消息传递机制的示例,并提供运行结果:

#include <iostream>
#include <functional>
#include <list>

class Message {
public:
    Message(int value) : data(value) {}

    int getData() const {
        return data;
    }

private:
    int data;
};

class EventBus {
public:
    static EventBus& getInstance() {
        static EventBus instance;
        return instance;
    }

    void publish(const Message& message) {
        for (auto& subscriber : subscribers) {
            subscriber(message);
        }
    }

    void subscribe(std::function<void(const Message&)> callback) {
        subscribers.push_back(callback);
    }

private:
    EventBus() {}

    std::list<std::function<void(const Message&)>> subscribers;
};

class ClassA {
public:
    ClassA() {
        EventBus::getInstance().subscribe(std::bind(&ClassA::handleMessage, this, std::placeholders::_1));
    }

    void sendMessage(int value) {
        Message message(value);
        EventBus::getInstance().publish(message);
    }

    void handleMessage(const Message& message) {
        std::cout << "ClassA received message with data: " << message.getData() << std::endl;
    }
};

class ClassB {
public:
    void handleMessage(const Message& message) {
        std::cout << "ClassB received message with data: " << message.getData() << std::endl;
    }
};

int main() {
    ClassA objA;
    ClassB objB;

    Message message(42);
    objA.sendMessage(message); // Output: ClassA received message with data: 42

    EventBus::getInstance().subscribe(std::bind(&ClassB::handleMessage, &objB, std::placeholders::_1));
    objA.sendMessage(100); // Output: ClassA received message with data: 100 \n ClassB received message with data: 100

    return 0;
}

在这个示例中,我们定义了一个 Message 类,表示传递的消息。然后,我们创建了一个简单的事件总线 EventBus,它允许订阅者通过 subscribe 方法订阅消息,并通过 publish 方法发布消息。ClassAClassB 分别作为消息的发送者和接收者。在 main() 函数中,我们创建了一个 ClassA 对象和一个 ClassB 对象,然后通过事件总线来传递消息。

在运行结果中,你将看到消息被成功传递并在接收者类中处理:

ClassA received message with data: 42
ClassA received message with data: 100
ClassB received message with data: 100

这个例子演示了如何使用简单的事件系统来模拟消息传递机制,在两个类的实例之间传递参数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/65450.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

pg实现月累计

获取每月累计数据&#xff1a; ​​​ SELECT a.month, SUM(b.total) AS total FROM ( SELECT month, SUM(sum) AS total FROM ( SELECT to_char(date("Joinin"),YYYY-MM) AS month , COUNT(*) AS sum FROM "APP_HR_Staff_Basic_Info" GROUP BY month ) …

做接口测试如何上次文件

在日常工作中&#xff0c;经常有上传文件功能的测试场景&#xff0c;因此&#xff0c;本文介绍两种主流编写上传文件接口测试脚本的方法。 首先&#xff0c;要知道文件上传的一般原理&#xff1a;客户端根据文件路径读取文件内容&#xff0c;将文件内容转换成二进制文件流的格式…

Vue3 第五节 一些组合式API和其他改变

1.provide和inject 2.响应式数据判断 3.Composition API的优势 4.新的组件 5.其他改变 一.provide和inject 作用&#xff1a;实现祖与后代组件间通信 套路&#xff1a;父组件有一个provide选项来提供数据&#xff0c;后代组件有一个inject选项来开始使用这些数据 &…

APP外包开发的学习流程

学习iOS App的开发是一项有趣和富有挑战性的任务&#xff0c;是一个不断学习和不断进步的过程。掌握基础知识后&#xff0c;不断实践和尝试新的项目将使您的技能不断提升。下面和大家分享一些建议&#xff0c;可以帮助您开始学习iOS App的开发。北京木奇移动技术有限公司&#…

hcip的重发布实验(1)

题目 拓扑图 IP地址配置 R1 < Huawei>sy Enter system view, return user view with CtrlZ. [Huawei]sysname r1 [r1]int l0 [r1-LoopBack0]ip add 1.1.1.1 24 [r1-LoopBack0]int g0/0/0 [r1-GigabitEthernet0/0/0]ip add 12.1.1.1 24 Aug 8 2023 21:28:29-08:00 r1 %%0…

升级node版本后vue2的项目node-sass、sass-loader安装报错(14.x升级到16.x)

node升级到16.x版本后&#xff0c;对应的node-sass需要升级到^6.0.0&#xff0c;此时sass-loader的版本需要升级到10.2.0以上 &#xff0c;具体对应版本规则可参考链接: https://github.com/webpack-contrib/sass-loader/releases?page3 vue2通过vue/cli创建的项目&#xff0…

super父类 事物

一个没有事物的方法。 调用他的父类里有事物的方法。 无论this 和 super 都会让父类事物方法没有事物。 如果写了super.class 文件里面&#xff0c;就是super调用。 如果没写&#xff0c;就是this调用&#xff0c;坑爹 测试&#xff0c;把父类注入&#xff0c;事物才生效。

搭建本地开发服务器

搭建本地开发服务器 :::warning 注意 在上一个案例的基础上添加本地开发服务器&#xff0c;请保留上个案例的代码。如需要请查看 Webpack 使用。 ::: 搭建本地开发服务器这一个环节是非常有必要的&#xff0c;我们不可能每次修改源代码就重新打包一次。这样的操作是不是太繁琐…

ArcGIS Pro基础:【划分】工具实现等比例、等面积、等宽度划分图形操作

本次介绍【划分】工具的使用&#xff0c;如下所示&#xff0c;为该工具所处位置。使用该工具可以实现对某个图斑的等比例面积划分、相等面积划分和相等宽度划分。 【等比例面积】&#xff1a;其操作如下所示&#xff0c;其中&#xff1a; 1表示先选中待处理的图斑&#xff0c;2…

无人机光伏巡检系统的全新作用解析,提升效率保障安全

随着光伏发电行业的快速发展&#xff0c;光伏电站的规模越来越大&#xff0c;光伏维护和巡检成为一个巨大的挑战。为解决传统巡检方法的低效率和安全风险问题&#xff0c;无人机光伏巡检系统应运而生&#xff0c;并成为提升光伏巡检效率和保障安全的利器。 首先&#xff0c;无人…

尚硅谷张天禹Vue2+Vue3笔记(待续)

简介 什么是Vue&#xff1f; 一套用于构建用户界面的渐进式JavaScript框架。将数据转变成用户可看到的界面。 什么是渐进式&#xff1f; Vue可以自底向上逐层的应用 简单应用:只需一个轻量小巧的核心库 复杂应用:可以引入各式各样的Vue插件 Vue的特点是什么&#xff1f; 1.采…

常用抓包工具

Fiddler Fiddler 是一个很好用的抓包工具&#xff0c;可以用于抓取http/https的数据包&#xff0c;常用于Windows系统的抓包&#xff0c;它有个优势就是免费 Charles Charles是由JAVA开发的&#xff0c;可以运行在window Linux MacOS&#xff0c;但它是收费的&#xff0c;和…

怎么在JMeter中的实现关联

我们一直用的phpwind这个系统做为演示系统, 如果没有配置好的同学, 请快速配置之后接着往下看哦. phpwind发贴时由于随着登陆用户的改变, verifycode是动态变化的, 因此需要用到关联. LoadRunner的关联函数是reg_save_param, Jmeter的关联则是利用后置处理器来完成. 在需要查…

Spark官方调优三部曲之三:其它优化思路

前言 前面介绍了关于spark性能调优两个最重要的点: 数据序列化内存调优这两个方向都进行调优后,如果想进一步继续优化你的程序,可以参考下面的思路。 设置合理的并行度 除非将每个操作的并行级别设置得足够高,否则集群资源不会得到充分利用。Spark根据每个文件的大小自动…

互联网电影购票选座后台管理系统源码开发

搭建一个互联网电影购票选座后台管理系统需要进行以下步骤&#xff1a; 1. 需求分析&#xff1a;首先要明确系统的功能和需求&#xff0c;包括电影列表管理、场次管理、座位管理、订单管理等。 2. 技术选型&#xff1a;选择适合的技术栈进行开发&#xff0c;包括后端开发语言…

kettle之Switch/Case 插件

Switch/Case 插件存在于转换中&#xff0c;用于进行分支选择 插件运行下一步的表输入中执行hivesql需选上下面红色方框的&#xff0c;否则Switch/Case分支不生效!

Node.js |(三)Node.js API:path模块及Node.js 模块化 | 尚硅谷2023版Node.js零基础视频教程

学习视频&#xff1a;尚硅谷2023版Node.js零基础视频教程&#xff0c;nodejs新手到高手 文章目录 &#x1f4da;path模块&#x1f4da;Node.js模块化&#x1f407;介绍&#x1f407;模块暴露数据⭐️模块初体验⭐️暴露数据 &#x1f407;导入文件模块&#x1f407;导入文件夹的…

【二叉树】105. 从前序与中序遍历序列构造二叉树

链接: 105. 从前序与中序遍历序列构造二叉树 先序 能够确定谁是根 中序 知道根之后&#xff0c;能够确定左子树和右子树的范围 例子 根据先序的性质&#xff08;根左右&#xff09;&#xff0c;能够确定根&#xff0c;我们就能够从总序中找出根节点&#xff08;rooti所在…

C语言刷题------(2)

C语言刷题——————&#xff08;2&#xff09; 刷题网站&#xff1a;题库 - 蓝桥云课 (lanqiao.cn) First Question&#xff1a;时间显示 题目描述 小蓝要和朋友合作开发一个时间显示的网站。 在服务器上&#xff0c;朋友已经获取了当前的时间&#xff0c;用一个整数表…

pytest自动化测试框架之断言

前言 断言是完整的测试用例中不可或缺的因素&#xff0c;用例只有加入断言&#xff0c;将实际结果与预期结果进行比对&#xff0c;才能判断它的通过与否。 unittest 框架提供了其特有的断言方式&#xff0c;如&#xff1a;assertEqual、assertTrue、assertIn等&#xff0c;py…