【问题标题】:Package accessibility for function and/or class函数和/或类的包可访问性
【发布时间】:2011-04-12 02:20:36
【问题描述】:

在 Java 中,它们具有包访问说明符,它使该函数只能由来自同一个“包”(命名空间)的类使用,我看到了它的好处。尤其是在模型设计发挥作用时。你认为这样的东西在 C++ 中可能有用吗?
谢谢。

【问题讨论】:

    标签: c++ language-features


    【解决方案1】:

    晚了“一点点”,但万一其他人降落在这里......;)

    有一个在 C++ 中模拟包的解决方案:利用内部类(也称为帮助类)的特殊性,它能够访问其外部类的任何成员,甚至是私有成员。

    例子:

    class Package
    {
    public:
        class Public;
    private:
        class Private;
    };
    
    • 任何人都可以使用公共课程。
    • 只有 Package 中的类可以使用私有类。

    这里有一个完整的例子(及其permalink):

    #include <iostream>
    
    // Package.hpp
    
    class Package
    {
    public:
        Package () = delete;
    
        class PublicClass;
    
    private:
        class PrivateClass;
    };
    
    // PrivateClass.hpp / cpp
    
    class Package::PrivateClass
    {
    public:
        PrivateClass ()
        {
            std::cout << "PrivateClass only usable by Package classes.\n";
        }
    
    private:
        void Forbidden () {}
    };
    
    // PrivateClass.hpp / cpp
    
    class Package::PublicClass
    {
    public:
        PublicClass ()
        {
            std::cout << "PublicClass usable from outside/inside Package.\n";
            Package::PrivateClass privateClass;
            // privateClass.Forbidden ();  // error: 'Forbidden' is a private member of 'Package::PrivateClass'
        }
    };
    
    // main.cpp
    
    int main ()
    {
        // Package package;  // error: call to deleted constructor of 'Package'.
    
        Package::PublicClass publicClass;
        //Package::PrivateClass privateClass;  // error: 'PrivateClass' is a private member of 'Package'
    
        return EXIT_SUCCESS;
    }
    
    // Output:
    // -------
    // PublicClass usable from outside/inside Package.
    // PrivateClass only usable by Package classes.
    

    【讨论】:

      【解决方案2】:

      正如其他人指出的那样,通常的做法只是按照惯例,但是 C++ 确实提供了friends,它允许您指定只有您指定的类/函数才能访问类的内部,例如私有函数,这可用于提供类似包的限制。

      在 C++ 中避免使用大多数朋友,因为它们往往会增加耦合

      实际上并没有直接的等价物,因为 C++ 不是例如旨在应对移动代码,:.无论如何,访问说明符是一种方便而不是安全功能。

      【讨论】:

        【解决方案3】:

        您可以为“包”的用户提供一个应该是“公共”的头文件。只能在内部使用的东西可以将它们的头文件放在一个名为“内部”或(包名)的文件夹中。这不会阻止某人实际包含这些文件,但您传达他不应该包含这些文件!

        【讨论】:

          【解决方案4】:

          是的,这可以实现。您可以通过公共、受保护、私有关键字以及源可见性来限制可见性。

          声明的可见性是普遍理解的。

          源代码可见性(如果您来自 Java)有点不同。

          Java:您有一个用于对象接口/实现的文件。 Cpp:你有一个接口文件。实现可能位于接口中,也可能位于一个或多个实现(cpp、cxx)文件中。

          如果您使用除了库的公共接口之外的抽象类/接口/函数,它们实际上是隐藏的并且不可访问(好吧,如果您有特别爱管闲事的用户转储符号,这是错误的——那么他们可能会重新声明接口,并链接到符号,但是......这显然是他们未定义的领域)。所以你只需要让你喜欢的符号可见。使用包/库命名约定来避免链接错误是一个好主意 - 将类放在为库的私有实现保留的命名空间中。很简单。

          它在 C++ 中有用吗...还不错,尽管我个人认为该语言有更高的优先级。

          源可见性示例:

          /* publicly visible header file */
          
          namespace MON {
          class t_button {
          protected:
              t_button();
              virtual ~t_button();
          public:
              typedef enum { Default = 0, Glowing = 1 } ButtonType;
              /* ... all public virtual methods for this family of buttons - aka the public interface ... */
          public:
              t_button* CreateButtonOfType(const ButtonType& type);
          };
          }
          
          /* implementation file -- not visible to clients */
          
          namespace MON {
          namespace Private {
          class t_glowing_button : public t_button {
          public:
              t_glowing_button();
              virtual ~t_glowing_button();
          public:
              /* ... impl ... */
          };
          }
          }
          
          MON::t_button* MON::t_button::CreateButtonOfType(const ButtonType& type) {
              switch (type) {
                  case Glowing :
                      return new Private::t_glowing_button();
          
                  case Default :
                      return new Private::t_glowing_button();
          
                      /* .... */
                  default :
                      break;
              }
          
              /* ... */
              return 0;
          }
          

          【讨论】:

          • 但是如果你把那些实际上不在接口中的函数放在同一个命名空间中的其他类不能使用它们可以吗?如果能举个例子就好了。
          • 如果发光按钮(在新添加的示例中)对其他类/接口可见,则可以使用它。你如何组织图书馆可能非常重要(或根本不重要),这取决于你想抽象多少。 fwiw,c++ 还提供了`friend's.所以... cpp 在这方面具有大部分 Java 的功能(可见性) - 这可能就是为什么包可见性功能对我个人而言不是高优先级的原因。
          【解决方案5】:

          一个Java包大致是:

          • 一种对源文件进行分组的方法
          • 创建压缩二进制文件

          在 C++ 中,第一个可以通过明智地使用 namespace 来实现。但是,没有办法使用语言结构来模拟后者。

          【讨论】:

            【解决方案6】:

            在 C++ 中,如果需要,请使用类。

            IMO,访问规则已经足够复杂了。

            (请注意,您可以拥有只包含 static 成员函数的类,从而有效地实现您想要的。)

            【讨论】:

            • 我不认为使用静态 fnc 可以实现这一点。假设您的 A 类只有静态成员。您仍然可以从声明该类的命名空间外部访问这些成员。我不明白您如何通过使用类来实现这一点?你能详细说明一下吗?
            • @A-ha 只需将静态函数的可见性更改为私有,然后尝试在类之外使用它——您将看到这是阻止客户使用私有的有效方法实施。编译器将拒绝该程序。
            • @Justin 是的,但它也会限制其他类使用这些函数,关键是使它们仅可用于同一命名空间中的类。所以实际上他们可以与这个类进行交互,但前提是它们与这个类在同一个命名空间中。
            • @A-ha:将class 用作namespace。 (当然,这样做的缺点是命名空间是开放的,而类则不是。)
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-07-04
            • 2011-07-23
            • 1970-01-01
            • 1970-01-01
            • 2015-08-12
            相关资源
            最近更新 更多