Qt小知識3.Q_DECLARE_PRIVATE和Q_DECLARE_PUBLIC

1 引言

當使用Qt開發C++應用程序時,可以使用Q_DECLARE_PUBLIC、Q_DECLARE_PRIVATE、Q_D和Q_Q宏來幫助隱藏和公開類的私有成員和方法。

先來看看它們長什麼樣子:

 #define Q_DECLARE_PRIVATE(Class) \
 inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(qGetPtrHelper(d_ptr)); } \
 inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(qGetPtrHelper(d_ptr)); } \
 friend class Class##Private;  

 #define Q_DECLARE_PUBLIC(Class) \
 inline Class* q_func() { return static_cast<Class *>(q_ptr); } \
 inline const Class* q_func() const { return static_cast<const Class *>(q_ptr); } \
 friend class Class;

#define Q_D(Class) Class##Private * const d = d_func()
#define Q_Q(Class) Class * const q = q_func()

Q_DECLARE_PUBLIC 和 Q_DECLARE_PRIVATE 這兩個宏一般成對使用,用於實現 PIMPL 設計模式,這樣可以達到隱藏實現的目的。

2 實際案例

假設現在正在開發一個音頻播放器應用程序,其中有一個名爲AudioPlayer的類負責播放音頻文件,這個類有一些私有成員和方法,需要通過一些公共函數和方法來訪問。

首先,在AudioPlayer類的頭文件中,使用Q_DECLARE_PRIVATE宏來聲明私有數據指針,這個指針將被用於存儲私有數據:

#ifndef AUDIOPLAYER_H
#define AUDIOPLAYER_H

#include <QObject>

class AudioPlayerPrivate;

class AudioPlayer : public QObject
{
    Q_OBJECT
    Q_DECLARE_PRIVATE(AudioPlayer)

public:
    explicit AudioPlayer(QObject *parent = nullptr);
    ~AudioPlayer();

    void play(const QString& audioFile);
    void stop();

private:
    QScopedPointer<AudioPlayerPrivate> d_ptr;
};

#endif // AUDIOPLAYER_H
#include "audioplayer.h"
#include "audioplayer_p.h"

AudioPlayer::AudioPlayer(QObject *parent)
    : QObject(parent),
      d_ptr(new AudioPlayerPrivate(this))
{
}

AudioPlayer::~AudioPlayer()
{
}

void AudioPlayer::play(const QString &audioFile)
{
    Q_D(AudioPlayer);
    // 使用d指針可以訪問私有成員和方法
    d->playInternal(audioFile);
}

void AudioPlayer::stop()
{
    Q_D(AudioPlayer);
    // 使用d指針可以訪問私有成員和方法
    d->stopInternal();
}

在這個例子中,使用了Q_D宏來定義一個d指針,該指針指向AudioPlayer類的私有數據。

在使用Q_D宏之前,需要在AudioPlayer類實現文件中包含一個名爲audioplayer_p.h的文件,其中聲明瞭AudioPlayerPrivate類,使用Q_DECLARE_PUBLIC宏來聲明公共類的指針:

#ifndef AUDIOPLAYER_P_H
#define AUDIOPLAYER_P_H

class AudioPlayer;
class AudioPlayerPrivate
{
    Q_DECLARE_PUBLIC(AudioPlayer)

public:
    AudioPlayerPrivate(AudioPlayer *audioPlayer);

    void playInternal(const QString &audioFile);
    void stopInternal();

private:
    AudioPlayer *q_ptr;
};

#endif // AUDIOPLAYER_P_H

然後,在audioplayer_p.cpp文件中,可以使用Q_Q宏來定義公共類的指針:

#include "audioplayer_p.h"
#include "audioplayer.h"

AudioPlayerPrivate::AudioPlayerPrivate(AudioPlayer *audioPlayer)
    : q_ptr(audioPlayer)
{
}

void AudioPlayerPrivate::playInternal(const QString &audioFile)
{
    // 使用q指針可以訪問公共函數和方法
    Q_Q(AudioPlayer);
    // ...
}

void AudioPlayerPrivate::stopInternal()
{
    // 使用q指針可以訪問公共函數和方法
    Q_Q(AudioPlayer);
    // ...
}

在這個例子中,使用了Q_Q宏來定義一個q指針,該指針指向AudioPlayer類。

總結

通過使用Q_DECLARE_PRIVATE、Q_DECLARE_PUBLIC、Q_D和Q_Q宏,可以在Qt應用程序中實現類的封裝和隱藏,同時提供公共接口來訪問私有成員和方法。這樣可以有效地封裝類的內部實現細節,提高代碼的可讀性和可維護性。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章