web-dev-qa-db-ja.com

PIMPLのパブリッククラスメンバー

PIMPLイディオムを使用しようとしています。これは、include/foo.hの公開ヘッダーファイルです。

class FooPrivate;

class Foo {
public:
        Foo();
        ~Foo();

private:
        FooPrivate* p_impl;
};

プライベートクラスはsrc/foo_private.hで定義され、src/*.cpp全体で使用されます。

class FooPrivate {
public:
        ...
private:
        ...
};

私の質問は、クラス全体がプライベートであるため、FooPrivatepublic:またはprivate:メンバーと関数を区別する理由は何ですか?これは、foo.hおよびlibfoo.soを、それを使用するエンドユーザーに配布する観点からのものです。

パブリックメンバーとプライベートメンバーに注意を払うと、正しいコーディング方法が適用されることになります。つまり、プライベートコードで使用するAPIを公開することを考えさせます。

一方、FooPrivateにすべてのパブリックメンバーを含めることで、ユニットテストを簡単に記述できるようになり、APIやアクセサーなどについて考える必要なく、コード内で簡単に渡すことができます。また、すべてがプライベートであるため、エンドユーザーはこのだらしの影響を受けません。

どっちがいい?

私はまだC++の初心者なので、私の仮定について間違っている可能性があることに注意してください。

更新

返信に基づいて、私は適切なときにパブリック/プライベートを使用し続けることに同意しました。

PIMPLの利点は、公開ヘッダーファイルを公開することなく、プライベートヘッダーファイルでgoogletestフレンドテストマクロを非表示にできることです。

#ifdef UNIT_TESTS
#include <gtest/gtest_prod.h>
#endif

class FooPrivate {
public:
        ...
private:
#ifdef UNIT_TESTS
        FRIEND_TEST(FooPrivate, Test1)
#endif
        ...
};

このようにして、必要なテストを記述できます。

プライベートメンバーのテストが良いかどうかは今や他のワームの缶のようです。

1
Sevag

クラス全体がプライベートなので、FooPrivateのpublic:またはprivate:メンバーと関数を区別する理由は何ですか?これは、配布の観点からですfoo.hおよびlibfoo.soを使用するエンドユーザーに。

Fooのユーザーの観点から見ると、プライベート関数やプライベートデータメンバーはもちろん、FooPrivateに関数を含める理由はまったくありません。

一方、FooPrivateの-​​authorの観点から見ると、他のクラスとまったく同じであると考える必要があります。その実装の詳細を偶発的な干渉から保護するためのプライベートセクションがあります。プライマリユーザーがPIMPLラッパークラス(Foo)であるという事実は、ここでは偶然です。

テストの理由から、FooPrivateからより豊富なインターフェイスを提供することを選択する場合がありますが、それでも、すべての内部を公開する理由にはなりません。