看下面例子:
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; // 用于线程安全
};