看下面例子:
class FileManager : public QObject {
Q_OBJECT
public:
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); //注意,这里是QApplication
FileManager 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); //注意,这里是QApplication
FileManager2 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-16
void changeFileName(const _string& oldPathName, const _string& newPathName);
/// <summary>
/// 更改文件夹名或路径
/// </summary>
/// <param name="oldPathName"></param>
/// <param name="newPathName"></param>
/// 创建时间:2025-03-16 最后一次修改时间:2025-03-16
void 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; // 用于线程安全
};