4

次のような状況があります。

namespace MyFramework {
  class A {
    void some_function_I_want_B_to_use() {}
  };
  class B {
    B() {
      some_function_I_want_B_to_use() {}
    }
  };
}

some_function_I_want_B_to_use名前空間の外では見えないようにしたいのMyFrameworkですが、MyFramework 内の誰にでも見えるようにしたいです (または、クラス B だけに見えるようにすることもできます)。このようなメソッドがいくつかありますが、MyFramework のパブリック API からそれらを非表示にして、すべてのクラスをMyFrameworkフレンド内に作成する唯一の方法はありますか? また、すべての「低レベル」クラスを B 内に配置することも検討していましたが、B 内からではなく B 内から A のすべてのメソッドにアクセスできることが確実になるまで、そのルートをたどりたくありません。 MyFramework の外部。

言い換えると、フレームワークはすべて 1 つの名前空間内で作成され、各クラスには、フレームワークを使用する一般の人々に役立つメソッドがあります。ただし、各クラスには、パブリック API を複雑にするが、フレームワークが適切に機能するために必要ないくつかのメソッドもあります。

4

3 に答える 3

4

some_function_I_want_B_to_use名前空間の外では を見えないようにしたいのMyFrameworkですが、 の中の誰にでも見えるようにしたいのですMyFramework

要約すると、Java のパッケージに似たものが必要です。

残念ながら、名前空間ではそれができません。名前空間に含まれるすべてのクラスは、名前空間の外側からアクセスできます。名前空間は開いています。

解決策は通常、実装の詳細のために別の名前空間を追加することです。

namespace MyFramework
{
    // Implementation details
    // Should not be used by the user
    namespace detail
    {
        class A
        {
            public:
                void func();
        };
    }

    class B
    {
        public:
            B()
            {
                A a;
                a.func();
            }
    };
}

detail名前空間がユーザーによって使用されないことを示すコメントを追加することを忘れないでください。

于 2013-03-19T23:49:45.987 に答える
2

Compilation Firewallと呼ばれることが多いPimpl idiomは、あなたが探しているものです。Qt全体がこのイディオムを使用して実装されています。

// A.hpp
namespace MyFramework {
  class A {
  private:
    class Private;

    Private* implementation;
  };
}

// A_Private.hpp
#include "A.hpp"

namespace MyFramework {
  class A::Private {
  public:
    void some_function_I_want_B_to_use() {}
  };
}

// A.cpp
#include "A_Private.hpp"

namespace MyFramework {
A::A() {
  implementation->some_function_I_want_B_to_use();
}
}

// B.hpp
#include "A.hpp"

namespace MyFramework {
  class B {
    B();

    A a;
  };
}

// B.cpp
#include "A_Private.hpp"

namespace MyFramework {
B::B() {
  a.implementation->some_function_I_want_B_to_use();
}
}

: もちろん、フレームワークの最終ディストリビューションA_Private.hppのディレクトリには移動しません。つまり、必要に応じてパッケージ プライベートのままです。include

この例は非常に基本的なものです。もちろん、より高度で堅牢にすることもできます。さらに、Pimplには他にも多くの利点があります. このすべての情報については、次を参照してください。

于 2013-03-20T00:10:54.503 に答える
2

Boost などの一般的な規則は、 と呼ばれるネストされた名前空間detailです。

アクセシビリティを強制したい場合は、代わりにネストさclassれた をいつでも使用できますdetail。このクラスはアクセシビリティ チェックを提供しますが、名前空間のような拡張性がありません。ただし、detailスコープの拡張が必要になることはめったにありません。

だから、そのすべての醜さにおいて、

namespace my_framework {
    class detail
    {
    private:
        static void some_function_I_want_B_to_use() {}

    public:
        class A
        {};

        class B
        {
            B() { some_function_I_want_B_to_use(); }
        };
    };

    typedef detail::A A;        // "using detail::A"
    typedef detail::B B;        // "using detail::B"
}  // namespace my_framework

ちなみに、クラス B (質問から直接) にはプライベートなデフォルト コンストラクターがあるため、そのインスタンスを作成できないことに注意してください。

于 2013-03-20T00:06:59.320 に答える