命名空间级访问

时间:2013-03-19 22:44:12

标签: c++ namespaces access-modifiers

我有以下情况:

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_useMyFramework命名空间之外不可见,但我确实希望MyFramework中的任何人都可以看到它(或者,只有B类可见也可以)。我有很多像这样的方法,是将它们隐藏在MyFramework的公共API中以便在MyFramework朋友中制作所有类的唯一方法吗?我也在考虑将所有“低级”类放在B中,但是我不想沿着这条路走下去,直到我确信它能够完成从B内部访问所有A方法的能力,但不是在MyFramework之外。

重申一下,我有一个框架,它都是在一个名称空间内创建的,每个类都有对使用框架的一般公众有用的方法。但是,每个类还有一些方法使公共API复杂化,但框架才能正常运行。

3 个答案:

答案 0 :(得分:3)

  

我希望some_function_I_want_B_to_useMyFramework命名空间之外不可见,但我确实希望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命名空间。

答案 1 :(得分: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类(直接来自问题)有一个私有默认构造函数,因此不能创建它的实例。

答案 2 :(得分:2)

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 还有很多其他优点。有关所有这些信息,请参阅: