6

私はC++ヘッダーを書いています。

class A {
   // ...
};

外の世界から隠したいのです(このヘッダーの将来のバージョンでは変更されるか、削除される可能性があるため)。

同じヘッダーに、クラスAのオブジェクトをメンバーとして持つクラスBもあります。

class B {
public:
   // ...

private:
   A a_;
};

クラスAを外界から隠す適切な方法は何ですか?

名前のない名前空間にAの定義を入れると、コンパイラーは警告を発行するので、内部リンケージの問題のために、別のことをする必要があると思います。

4

7 に答える 7

10

C ++でそれを実行する正しい方法は、PIMPLイディオムです。別の解決策は、非表示にするクラスをネストされた名前空間に配置することです。これは通常、と呼ばれdetailます。ただし、ユーザーは引き続き依存関係にさらされ、直接使用できるため、完全にプライベートになるわけではありません。

于 2011-04-25T17:18:21.033 に答える
5

あなたは内部クラスを行うことができます:

class B
{
  class A { /* ... */ };
  A a_;
}
于 2011-04-25T17:14:54.423 に答える
2

このクラスはパブリックAPIの一部ではないため、使用しないでください。

C ++では、他に選択肢がほとんどないため、ライブラリコードにリンクする信頼できるプログラムを使用する必要があります。C ++には制限された「アクセス制御」機能があり、その多くはバイパスまたは悪用される可能性があるため、APIクライアントを尊重して扱い、信頼を構築する方が適切です。

APIを正しく使用しやすく、意図せずに誤って使用しにくいように設計すると、クライアントを支援することになり、クライアントがインターフェイスを悪用しても問題はほとんどありません。

于 2011-04-25T17:20:57.540 に答える
2

名前のない名前空間は、複数の定義を保護するだけなので、とにかく役に立たない。他の回答で述べられているように、pImpl Idiomを使用するか、detail名前空間を使用することができます。Boostでは問題なく動作します:

namespace detail{
  class A{
    // ...
  };
}

class B{
public:
  // ...
private
  A a_;
};

名前空間にあるものをいじる人は誰でもdetail問題を求めています。または多分それをさらに曖昧にする

namespace _b_impl_detail{
  // ...
};

今、中の何かに触れた人は誰でも足を撃たれるべきです。:)

于 2011-04-25T17:26:03.740 に答える
1

オブジェクトを保持するclass B代わりに、代わりに(または、、、など)を保持するようにします。この方法では、の前方宣言のみが必要であり、のソースファイル内で完全に定義できます。AA*shared_ptr<A>unique_ptr<A>class Bclass Aclass Aclass B

于 2011-04-25T17:15:29.227 に答える
1

AがBの実装の詳細である場合、その定義をヘッダーにまったく入れないでください。その代わり:

class B {

   ...
   class A * myA;
};

次に、Aの定義をB実装(つまり、.cpp)ファイルに入れます。

于 2011-04-25T17:17:50.243 に答える
0

https://stackoverflow.com/a/5780976/1525238に少しずつ追加して、「メイン」クラスがテンプレートで「ヘルパー/インナー」という特殊なユースケースをより適切に解決できるようにしたいと思います。クラスもテンプレート1である必要があります。

と呼ばれるネストされた名前空間を使用し、detailすべての「ヘルパー」コンテンツをプライベートにし、「メイン」クラスfriendを「ヘルパー」クラスのaにしました。

template<__MAIN_TEMPLATE_PARAMS__> class Main;

namespace detail {
    template<__HELPER_TEMPLATE_PARAMS__> class Helper {

        /* All Main templates are friends */
        template<__MAIN_TEMPLATE_PARAMS__> friend class Main; 

        /* Private stuff, not reachable from the outside */
        static void privateThing(){
            ...
        }
    };
}

template<__MAIN_TEMPLATE_PARAMS__> class Main {
    void usePrivateThing(){
        detail::Helper<__DESIRED_HELPER_TEMPLATE_PARAMS__>::privateThing();
    }
};

プライベートなものはstatic、コードを短くするためだけに上にあります。それらはインスタンスに非常によく結びついている可能性がありHelperます。

振り返ってみると、黒魔術が少ないよりエレガントなソリューションがあることは確かですが、それは特定のアプリケーションに大きく依存します。私はまだ上記をクラスの合法で良いユースケースだと思っていますfriend


1これは、部分的な特殊化を必要とするテンプレートヘルパー関数を使用する必要があったためです。これは、特別な理由はありませんが、ラッパークラスで技術的に可能です。簡単にするために、上記では部分的な特殊化を省略しています。

于 2019-12-23T17:09:25.050 に答える