Package accessibility for function and/or class

风流意气都作罢 提交于 2019-12-01 17:05:36

Yes, this can be accomplished. You may restrict visibility by public, protected, private keywords, as well as source visibility.

Declared visibility is commonly understood.

Source visibility (if you're coming from Java) is a bit different.

Java: you have one file for an object interface/implementation. Cpp: you have one file for an interface. the implementation may lie in the interface, or one or more implementation (cpp, cxx) files.

If you use abstract classes/interfaces/functions apart from the public interface of the library, they are effectively hidden and not accessible (well, this is false if you have particularly nosy users who dump symbols -- then they may redeclare the interface, and link to the symbols but... that's obviously undefined territory for them). So you only need to make the symbols you like visible. It's a good idea to use a package/library naming convention to avoid linking errors - place the classes in a namespace reserved for the library's private implementation. Simple.

Would it be useful in C++... it's not bad, although I personally think there are higher priorities for the language.

example of source visibility:

/* 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;
}

As others have pointed out the usual way to do this is just by convention however C++ does provide friends which would allow you to specify that only the classes/functions you specify can access internals of a class e.g. private functions, this can be used to provide package like restrictions.

Mostly friends are avoided in C++ as they tend to increase coupling

There isn't really a direct equivalent because C++ isn't e.g. designed to cope with mobile code, :. access specifiers are a conveneince not a security feature anyway.

A Java package is roughly:

  • A way of grouping source files
  • Creating compressed binaries

In C++, the first can be achieved via judicious usage of namespace. There is no way to emulate the latter using a language construct though.

In C++, if you need this, then use classes.

IMO, Access rules are complicated enough as they are.

(Note that you can have classes which contain nothing but static member functions, effectively implementing what you want.)

you could provide a header file which should be "public" for users of the "package". The stuff that should be used internally only can have their header files in a folder called "internal" or (package name). This does not prevent someone to actually include those files, but you communicate that he should not!

a "little bit" late, but in case other people land here... ;)

There is a solution to simulate packages in C++: To use the particularity of inner classes (also called helper classes), which are able to access any member of their outter class, even the private ones.

Example:

class Package
{
public:
    class Public;
private:
    class Private;
};
  • Anyone can use public classes.
  • Only classes from Package can use private classes.

Here a full example (and its 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.
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!