[Qt] ユーザ定義・独自クラスのデータをQDebugで出力する

目的

Studentクラスを例に説明します。

// student.h
class Student
{
    private:
        QString name_;
        int age_;
        int japanese_;
        int math_;
    public:
        QString getName(){ return name_; }
        int getAge(){ return age_; }
        int getJapanese(){ return japanese_; }
        int getMath(){ return math_; }
}

Studentクラスの状態をデバッグしたいとき、以下のように出力することができます。

// main.cpp
...
qDebug() << "name" << student.getName();
qDebug() << "age" << student.getAge();
qDebug() << "japanese" << student.getJapanese();
qDebug() << "math" << student.getMath();

しかし、本来必要のない大量のgetterを用意する必要があります。また、メンバを追加した際にデバッグ箇所を修正してまわる必要が出てきてしまいます。

以下のように書けると便利ですね。

// main.cpp
qDebug() << student;

もちろんこのままではエラーになります。

エラー: no match for 'operator<<' (operand types are 'QDebug' and 'Student')
  qDebug() << student;
           ^

QDebugと独自クラスのストリーム演算子が定義されていないというエラーメッセージが出ています。必要な定義を追記していきましょう。

QDebugと独自クラスのストリーム演算子の宣言・定義

宣言

まず、宣言は以下のようにクラス内で行います。()

// Student.h

class Student
{
private:
  QString name_;
  int age_;
  int japanese_;
  int math_;

public:
  Student():name_(""), age_(0), japanese_(0), math_(0){}

  // QDebug用定義。Studentのメンバ関数ではない。
  // friend関数にすることで、Studentクラスのprivateメンバにアクセスできる。
  friend QDebug operator<<(QDebug dbg, const Student &student);
};

定義

定義は.cppファイルにて行います。

// Student.cpp

#include "Student.h"
#include <QDebugStateSaver>
QDebug operator<<(QDebug dbg, const Student &c)
{
  // QDebugの状態を保存。
  // QDebugStateSaverインスタンス破棄時に状態が復元される
  QDebugStateSaver saver(dbg);

  // 自動でスペースを出力しないよう設定
  dbg.nospace();

  // Studentクラスのデータを出力
  dbg << "Student(";
  dbg << "name: " << c.name_ << ", ";
  dbg << "age: " << c.age_ << ", ";
  dbg << "japanese: " << c.japanese_ << ", ";
  dbg << "math: " << c.math_;
  dbg << ")";

  return dbg;
}

以上の宣言と定義をすませたうえで、以下コードを実行してみましょう。

// main.cpp

#include <QCoreApplication>

#include "Student.h"
#include <QDebug>

int main(int argc, char *argv[])
{
  QCoreApplication a(argc, argv);

  Student student;

  // Student(name: "", age: 0, japanese: 0, math: 0)
  qDebug() << student;

  return a.exec();
}
Student(name: "", age: 0, japanese: 0, math: 0)

と出力されていれば成功です。メンバの追加に応じてストリーム演算子の実装内容を追加するだけでOK。

おつかれさまでした。

サンプルコード

Qt環境があればそのままインポートして実行できるサンプルコードをこちらにまとめてあります。