2013-03-19 125 views
1

我有以下情况:命名空间级别的访问

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内部访问A的所有方法但不能从在MyFramework之外。

重申一下,我有一个全部在一个命名空间内创建的框架,并且每个类都有一些对使用框架的公众有用的方法。但是,每个类也有一些方法会使公共API复杂化,但是框架需要正常运行。

+0

什么是 “看得见” 是什么意思?如果函数的名字可以在头文件中找到,但函数是'private',它是否可见?没有(为我的目的) – anatolyg 2013-03-19 22:53:55

+0

。我希望能够列出“公共”API是唯一的公共方法。例如。有3种公共方法使得类的使用清晰,但有20多种方法使得类的使用更不明显 – Hamy 2013-03-19 22:55:50

+0

做some_function_I_want_B_to_use需要是A的一种方法吗?或者它可能是MyFramework中的命名空间函数? – EHuhtala 2013-03-19 23:02:08

回答

3

我想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命名空间不被用户使用。

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类(直接从问题)有没有这样的情况下,它可以创建一个私有的默认构造函数。

0

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

+1

如果仅需要头标模块,该怎么办? – 2013-03-20 00:12:37

+0

@干杯和hth。 - Alf,那么,你运气不好,这就是为什么'Boost'使用'detail'命名空间惯例的原因(轻微的开销是另一个原因)。然而,作者没有提供这样的要求,因此这个解决方案完全符合他的问题。 – 2013-03-20 00:17:58