欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 产业 > 接上一篇,C++中,如何设计等价于Qt的信号与槽机制。

接上一篇,C++中,如何设计等价于Qt的信号与槽机制。

2025/3/18 17:13:53 来源:https://blog.csdn.net/weixin_42944928/article/details/146295628  浏览:    关键词:接上一篇,C++中,如何设计等价于Qt的信号与槽机制。

看下面例子:


class FileManager : public QObject {Q_OBJECTpublic:FileManager(QObject* parent = nullptr) : QObject(parent) {}void changeFileName(const QString& newName) {fileName = newName;emit fileNameChanged(fileName);}signals:void fileNameChanged(const QString& newName);private:QString fileName;
};

所有连接类FileManage中的信号,在changeFileName函数中被调用。例如:

int main(int argc, char* argv[])
{QApplication a(argc, argv);  //注意,这里是QApplicationFileManager fm;QObject::connect(&fm, &FileManager::fileNameChanged, [](const QString& newName) {std::cout << "函数1收到:文件名改变了。\n";});QObject::connect(&fm, &FileManager::fileNameChanged, [](const QString& newName) {std::cout << "函数2收到:文件名改变2。\n";});fm.changeFileName("abc");return a.exec();
}

输出:

下面我们也来设计相同功能的FileManager2:

class FileManager2 {
public:using fileNameChanged = std::function<void(const QString& newName)>;public:std::list< fileNameChanged> fileNameChanged_list;
public:FileManager2(QObject* parent = nullptr) {}void changeFileName(const QString& newName) {fileName = newName;for (fileNameChanged&  f: fileNameChanged_list) {if (f != 0)f(newName);}}void connect(fileNameChanged f) {fileNameChanged_list.push_back(f);}
private:QString fileName;
};int main(int argc, char* argv[])
{QApplication a(argc, argv);  //注意,这里是QApplicationFileManager2 fm;fm.connect([](const QString& newName) {std::cout << "函数1收到:文件名改变了。\n";});fm.connect([](const QString& newName) {std::cout << "函数2收到:文件名改变。\n";});fm.changeFileName("abc");return a.exec();
}

输出:

是不是一样,是不是很酷。:)

关键地方:

这里相当于Qt中的emit

这里添加一个函数指针,上篇说过:

这里可连接N个Lambda 表达式,与Qt一样:

连接函数:

最终也一样:

由于临时灵感来了,用了几分钟写的,难免有问题, 如果使用
std::list::remove 会编译不了,现在用新版方案替代,以后再完善:

template<class T>
class _callback {
public:friend bool  operator==(const _callback& l, const _callback& r) {return l.m_id == r.m_id;}_callback(const T& pf) {m_pf = pf;m_id = _DateTime::g_timeStamp();}public:__int64 m_id;T m_pf;
};class _FileManager {
public:using pf_fileNameChanged = std::function<void(const _string& oldPathName,const _string& newPathName)>;/// <summary>/// 更改文件名或路径并通知所有订阅者/// </summary>/// <param name="oldPathName"></param>/// <param name="newPathName"></param>/// 创建时间:2025-03-16    最后一次修改时间:2025-03-16void changeFileName(const _string& oldPathName, const _string& newPathName);/// <summary>/// 更改文件夹名或路径/// </summary>/// <param name="oldPathName"></param>/// <param name="newPathName"></param>/// 创建时间:2025-03-16    最后一次修改时间:2025-03-16void changeFolderName(const _string& oldPathName, const _string& newPathName);/// <summary>/// 删除文件/// </summary>/// <param name="fileName"></param>void deleteFile(const _string& fileName);/// <summary>/// 删除文件夹/// </summary>/// <param name="folderName"></param>void deleteFolder(const _string& folderName);// 订阅文件名更改事件void subscribe(const pf_fileNameChanged& callback) {std::lock_guard<std::mutex> lock(m_mutex); // 线程安全m_fileNameChanged.push_back(callback);}// 取消订阅文件名更改事件void unsubscribe(const pf_fileNameChanged& callback) {std::lock_guard<std::mutex> lock(m_mutex); // 线程安全m_fileNameChanged.remove(callback);}private:_string m_dirPathName; // 当前文件名std::list<_callback<pf_fileNameChanged>> m_fileNameChanged; // 订阅者列表mutable std::mutex m_mutex; // 用于线程安全
};

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词