📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)

 
(同じ利用者による、間の6版が非表示)
200行目: 200行目:
<u>後方互換性のためにサポートされている。</u><br>
<u>後方互換性のためにサポートされている。</u><br>
<br>
<br>
==== Q_DISABLE_COPY / Q_DISABLE_MOVE ====
<code>Q_DISABLE_COPY</code>マクロは、クラスのコピーコンストラクタとコピー代入演算子を削除する。<br>
これにより、クラスのインスタンスが誤ってコピーされることを防ぐ。<br>
<br>
<code>Q_DISABLE_MOVE</code>マクロは、クラスのムーブコンストラクタとムーブ代入演算子を削除する。<br>
これにより、クラスのインスタンスが移動されることを防ぐ。<br>
<br>
これらのマクロは、以下に示すようなメリットがある。<br>
* オブジェクトの意図しない複製や移動を防ぐことができる。
* リソースの所有権に関する問題を回避できる。
* クラスの設計意図を明確に示すことができる。
<br>
以下の例では、クラスのインスタンスがコピーや移動されることを防ぐ方法を示している。<br>
これにより、意図しないオブジェクトの複製や移動を防ぎ、リソース管理を適切に行うことができる。<br>
<br>
<syntaxhighlight lang="c++">
// NonCopyable.hファイル
class NonCopyable
{
private:
    Q_DISABLE_COPY(NonCopyable)
public:
    NonCopyable()  = default;
    ~NonCopyable() = default;
    void doSomething() { qDebug() << "Doing something"; }
};
</syntaxhighlight>
<br>
<syntaxhighlight lang="c++">
// NonMovable.hファイル
class NonMovable
{
private:
    Q_DISABLE_MOVE(NonMovable)
public:
    NonMovable()  = default;
    ~NonMovable() = default;
    void doSomething() { qDebug() << "Doing something"; }
};
</syntaxhighlight>
<br>
<syntaxhighlight lang="c++">
// 使用例
#include "NonCopyable.h"
#include "NonMovable.h"
void testNonCopyable()
{
    NonCopyable nc1;
    // NonCopyable nc2 = nc1;  // コンパイルエラー: コピーコンストラクタは削除されている
    // NonCopyable nc3(nc1);  // コンパイルエラー: コピーコンストラクタは削除されている
    // nc1 = NonCopyable();    // コンパイルエラー: コピー代入演算子は削除されている
    nc1.doSomething();        // コンパイル可能
}
void testNonMovable()
{
    NonMovable nm1;
    // NonMovable nm2 = std::move(nm1);  // コンパイルエラー: ムーブコンストラクタは削除されている
    // nm1 = NonMovable();              // コンパイルエラー: ムーブ代入演算子は削除されている
    nm1.doSomething();                  // コンパイル可能
}
int main()
{
    testNonCopyable();
    testNonMovable();
    return 0;
}
</syntaxhighlight>
<br>
==== Q_FLAG / Q_FLAGS ====
列挙型をQtのメタオブジェクトシステムに登録するために使用する。<br>
<code>Q_FLAG</code>マクロは単一の列挙型、<code>Q_FLAGS</code>マクロは複数の列挙型を登録する。<br>
<br>
これにより、列挙型の値を文字列に変換する、または、QMLで使用することが可能になる。<br>
<br>
<syntaxhighlight lang="c++">
class Window : public QObject
{
    Q_OBJECT
public:
    enum Option {
      NoOption    = 0x0,
      ShowTitle  = 0x1,
      ShowButtons = 0x2
    };
    Q_FLAG(Option)
    enum Mode {
      Normal,
      Fullscreen
    };
    Q_ENUM(Mode)
    Q_FLAGS(Options, Option)
public:
    Window(QObject *parent = nullptr) : QObject(parent) {}
};
</syntaxhighlight>
<br>
<syntaxhighlight lang="c++">
// 使用例
void useEnums()
{
    Window window;
    QMetaEnum optionEnum = QMetaEnum::fromType<Window::Option>();
    qDebug() << optionEnum.valueToKey(Window::ShowTitle);  // 出力: "ShowTitle"
}
</syntaxhighlight>
<br>
==== Q_CLASSINFO ====
==== Q_CLASSINFO ====
クラスに関する追加のメタデータを定義するために使用する。<br>
クラスに関する追加のメタデータを定義するために使用する。<br>
353行目: 482行目:
     return 0;
     return 0;
  }
  }
</syntaxhighlight>
<br>
==== Q_DECLARE_PRIVATE / Q_DECLARE_PUBLIC ====
これは、Qtのプライベート実装パターンと共有データの管理に関連している。<br>
<br>
Qtのd-pointerイディオムを実装するために使用する。<br>
このパターンは、クラスの実装詳細を隠蔽して、バイナリ互換性を維持するのに役立つ。<br>
<br>
また、プライベートクラスとパブリッククラス間で相互にアクセスが可能となる。<br>
<br>
<syntaxhighlight lang="c++">
// MyClass.hファイル
#include "MyClassPrivate.h"
class MyClassPrivate;
class MyClass
{
private:
    Q_DECLARE_PRIVATE(MyClass)
    MyClassPrivate *d_ptr;
public:
    MyClass() : d_ptr(new MyClassPrivate(this))
    {}
    ~MyClass()
    {
      delete d_ptr;
    }
    void doSomething()
    {
      Q_D(MyClass);
      d->internalFunction();
    }
};
</syntaxhighlight>
<br>
<syntaxhighlight lang="c++">
// MyClassPrivate.hファイル
class MyClassPrivate
{
public:
    MyClassPrivate(MyClass *q) : q_ptr(q) {}
    void MyClassPrivate::internalFunction()
    {
      Q_Q(MyClass);
      // publicクラスのメンバーにアクセスできる
      someData = 42;
    }
    MyClass *q_ptr;
    Q_DECLARE_PUBLIC(MyClass)
    int someData;
};
</syntaxhighlight>
<br>
==== Q_DECLARE_SHARED ====
暗黙的な共有 (implicit sharing) を使用するクラスを宣言するために使用する。<br>
これにより、クラスのインスタンスを効率的にコピーできる。<br>
<br>
これは、メモリ使用量を削減でき、大きなオブジェクトの不必要なコピーを避けることができる。<br>
<br>
<syntaxhighlight lang="c++">
// MySharedData.hファイル
#include <QSharedData>
#include <QSharedDataPointer>
#include "MySharedDataPrivate.h"
class MySharedDataPrivate;
class MySharedData
{
private:
    QSharedDataPointer<MySharedDataPrivate> d;
public:
    MySharedData() : d(new MySharedDataPrivate) {}
    MySharedData::MySharedData(const MySharedData &other) : d(other.d) {}
    MySharedData &operator=(const MySharedData &other)
    {
      if (this != &other)
      d = other.d;
      return *this;
    }
    ~MySharedData(){}
    void setValue(int value)
    {
      d->value = value;
    }
    int MySharedData::value() const
    {
      return d->value;
    }
};
// クラスの宣言に関連する情報を提供して、
// そのクラスを使用するコードがこの情報にアクセスする必要があるため、ここで宣言する
Q_DECLARE_SHARED(MySharedData)
</syntaxhighlight>
<br>
<syntaxhighlight lang="c++">
// MySharedDataPrivate.hファイル
#include <QSharedData>
class MySharedDataPrivate : public QSharedData
{
public:
    MySharedDataPrivate() : value(0) {}
    MySharedDataPrivate(const MySharedDataPrivate &other) : QSharedData(other), value(other.value) {}
    int value;
};
</syntaxhighlight>
<br>
<syntaxhighlight lang="c++">
// 使用例
void useSharedData()
{
    MySharedData data1;
    data1.setValue(42);
    MySharedData data2 = data1;  // データは共有される
    data2.setValue(100);        // この時点で、データのコピーが作成される
    qDebug() << data1.value();  // 出力: 42
    qDebug() << data2.value();  // 出力: 100
}
</syntaxhighlight>
<br>
==== Q_D / Q_Q ====
d-pointerイディオムの実装時において、privateクラスとpublicクラス間のアクセスを容易にする。<br>
<br>
Q_Dマクロは、publicクラスからprivateクラスにアクセスするために使用する。<br>
Q_Qマクロは、privateクラスからpublicクラスにアクセスするために使用する。<br>
<br>
これらのマクロを使用することにより、以下に示すようなメリットがある。<br>
* private実装とpublicインターフェース間のアクセスを簡潔に記述することができる。
* タイプセーフなアクセスが可能になる。
* ソースコードの可読性が向上する。
<br>
以下の例では、publicクラスとprivateクラス間で相互にアクセスする方法を示している。<br>
これにより、実装の詳細を隠蔽しつつ、必要な場合に内部データにアクセスすることができる。<br>
<syntaxhighlight lang="c++">
// MyClass.hファイル
#include "MyClassPrivate.h"
class MyClassPrivate;
class MyClass
{
private:
    Q_DECLARE_PRIVATE(MyClass)
    MyClassPrivate *d_ptr;
public:
    MyClass() : d_ptr(new MyClassPrivate(this)) {}
    ~MyClass()
    {
      delete d_ptr;
    }
    void publicMethod()
    {
      Q_D(MyClass);  // d は MyClassPrivate* 型
      d->privateMethod();
      qDebug() << "Public method called, someData:" << d->someData;
    }
};
</syntaxhighlight>
<br>
<syntaxhighlight lang="c++">
// MyClassPrivate.hファイル
class MyClassPrivate
{
public:
    MyClassPrivate(MyClass *q) : q_ptr(q) {}
    void privateMethod()
    {
      Q_Q(MyClass);  // qはMyClass*型
      someData = 42;
      qDebug() << "Private method called by" << q;
    }
    MyClass *q_ptr;
    Q_DECLARE_PUBLIC(MyClass)
    int someData;
};
  </syntaxhighlight>
  </syntaxhighlight>
<br><br>
<br><br>
503行目: 835行目:
<br>
<br>
<code>Q_ARG</code>マクロは、Qtのシグナル / スロットシステムと密接に関連しており、Qtプログラミングにおいて柔軟なメソッド呼び出しを実現するための重要なツールの1つである。<br>
<code>Q_ARG</code>マクロは、Qtのシグナル / スロットシステムと密接に関連しており、Qtプログラミングにおいて柔軟なメソッド呼び出しを実現するための重要なツールの1つである。<br>
<br><br>
== プラットフォームに関するマクロ ==
* Q_OS_WINDOWS
* Q_OS_LINUX
* Q_OS_MACOS
* Q_OS_IOS
* Q_OS_ANDROID
<br>
上記のマクロは、特定のOS向けのコードを条件付きでコンパイルするために使用する。<br>
OS固有の機能や最適化を実装する場合に、ソースコードの可読性を保ちながら異なるOS向けの処理を記述することができる。<br>
<br>
使用例としては、以下に示すようなケースが考えられる。<br>
* ファイルシステムのパス区切り文字の違いに対応する。
* OS固有のAPIを使用する。
* GUIの外観や振る舞いをプラットフォームに合わせて調整する。
* デバイス固有の機能 (例: iOSやAndroidのセンサ) にアクセスする。
<br>
<syntaxhighlight lang="c++">
// PlatformSpecificWidget.hファイル
#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QVBoxLayout>
#include <QDebug>
class PlatformSpecificWidget : public QWidget
{
public:
    PlatformSpecificWidget(QWidget *parent = nullptr) : QWidget(parent)
    {
      QVBoxLayout *layout = new QVBoxLayout(this);
      QPushButton *button = new QPushButton("Click me", this);
      layout->addWidget(button);
      connect(button, &QPushButton::clicked, this, &PlatformSpecificWidget::onButtonClicked);
    }
private slots:
    void onButtonClicked()
    {
      #if defined(Q_OS_WINDOWS)
          qDebug() << "Hello from Windows!";
          // Windows固有のAPI呼び出し等を記述
      #elif defined(Q_OS_LINUX)
          qDebug() << "Hello from Linux!";
          // Linux固有の処理を記述
      #elif defined(Q_OS_MACOS)
          qDebug() << "Hello from macOS!";
          // MacOS固有の処理を記述
      #elif defined(Q_OS_IOS)
          qDebug() << "Hello from iOS!";
          // iOS固有の処理を記述
      #elif defined(Q_OS_ANDROID)
          qDebug() << "Hello from Android!";
          // Android固有の処理を記述
      #else
          qDebug() << "Hello from an unknown platform!";
      #endif
      // プラットフォーム共通の処理
      qDebug() << "This code runs on all platforms.";
    }
};
</syntaxhighlight>
<br>
<syntaxhighlight lang="c++">
// main.cppファイル
#include "PlatformSpecificWidget.h"
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    PlatformSpecificWidget widget;
    widget.show();
    return app.exec();
}
</syntaxhighlight>
<br><br>
<br><br>