QOverloadの必要性と基本概念
Qtフレームワークでは、シグナルとスロットの接続時にオーバーロードされたシグナルを扱う場合、型安全な方法で接続する必要があります。QOverloadテンプレートクラスはこの問題を解決するために提供されています。
ネットワーク接続確認の実装例
ホスト間のネットワーク到達性を確認するために、非同期Pingチェッカーを実装します。UIスレッドをブロックせずにバックグラウンドで実行するため、QProcessを使用します。
#include <QApplication>
#include <QTimer>
#include <QProcess>
#include <QDebug>
class NetworkMonitor : public QObject
{
Q_OBJECT
public:
explicit NetworkMonitor(QObject *parent = nullptr)
: QObject(parent)
{
monitorTimer = new QTimer(this);
monitorTimer->setInterval(3000); // 3秒間隔で監視
connect(monitorTimer, &QTimer::timeout,
this, &NetworkMonitor::performNetworkCheck);
monitorTimer->start();
}
private slots:
void performNetworkCheck()
{
QString targetHost = "192.168.1.1"; // 監視対象ホスト
QProcess* networkProcess = new QProcess(this);
QStringList arguments;
arguments << "-n" << "1" << targetHost; // Windows環境用
networkProcess->start("ping", arguments);
connect(networkProcess,
QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, [this, targetHost](int resultCode, QProcess::ExitStatus status) {
QString output = networkProcess->readAllStandardOutput();
bool hostAvailable = output.contains("TTL=") ||
output.contains("bytes from");
if (hostAvailable) {
qDebug() << "ネットワーク接続正常:" << targetHost;
} else {
qDebug() << "ネットワーク接続異常:" << targetHost;
}
networkProcess->deleteLater();
});
}
private:
QTimer *monitorTimer;
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
NetworkMonitor monitor;
return app.exec();
}
QOverloadの詳細説明
QProcessクラスのfinishedシグナルは複数のオーバーロードバージョンを持っています:
- finished(int exitCode, QProcess::ExitStatus exitStatus)
- finished(int exitCode)
これらのオーバーロードされたシグナルを正しく接続するために、QOverloadテンプレートを使用します。テンプレートパラメータとしてスロット関数の引数型を指定します。
使用例:
// 正しい接続方法
connect(process,
QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
receiver, &Receiver::handleProcessFinish);
// コンパイルエラーとなる誤った接続
// connect(process, &QProcess::finished, // あいまいな接続
// receiver, &Receiver::handleProcessFinish);
QOverloadの利点:
- 型安全性の確保
- コンパイル時のエラーチェック
- 明示的なシグナルバージョンの指定
実装では、ラムダ式を使用してQProcessの完了を非同期に処理します。deleteLater()を呼び出すことで、メモリリークを防止します。