Como tornar uma classe privada dentro de um espaço de nomes em C++?

Como tornar uma classe privada dentro de um espaço de nomes em C++ e impedir que outros acedam à classe fora do espaço de nomes, por exemplo:

namespace company{
    class MyPublicClass{ ... }  // This should be accessible 
    class MyPrivateClass{ ... } // This should NOT be accessible
}
Author: Daniel Santos, 2016-08-05

3 answers

Você não pode ter especificadores de Acesso para espaços de nomes, mas você pode para classes:

class company {
    // Private (default)
    class MyPrivateClass { ... };

public:
    class MyPublicClass { ... };
};

Você acede às classes tal como para um espaço de nomes com o operador de escopo:

company::MyPublicClass my_public_object;
Se a classe " pública "deve ter acesso à classe" privada", então a classe" privada" deve ser uma classe "pública".

Existe também outra maneira, que é simplesmente não ter a definição MyPrivateClass num ficheiro de cabeçalho público. Ou define a classe na fonte ficheiro, ou num ficheiro de cabeçalho privado apenas incluído internamente.

Qual a maneira de escolher depende do seu design e casos de uso.

 4
Author: Some programmer dude, 2016-08-05 17:49:14
Não podes.

Os espaços de nomes C++ não fornecem nenhum acessor com escopo, nem as declarações de classes (vs c#, por exemplo).

A forma habitual é introduzir um espaço de nomes internal para indicar public que o uso não é pretendido.

Você pode restringir o acesso usando friend especificadores.

Você também pode usar alguns truques, para tornar mais difícil o acesso a uma interface publicamente como explicado aqui: Como posso remover/remodelar uma declaração de dependência de "amigo" adequadamente?

 4
Author: πάντα ῥεῖ, 2017-05-23 10:33:50

Pode usar unnamed namespace. Os nomes que aparecem em um espaço de nomes Sem Nome têm ligação interna, mas os nomes que aparecem em um espaço de nomes nomeado e não têm nenhum especificador de classe de armazenamento, por padrão, têm ligação externa.

Por exemplo, temos um ficheiro chamado source1.cpp:
//source1.cpp
namespace company{
    class MyPublicClass{ ... };
    namespace{
        class MyPrivateClass{ ... };
    }
}
void f1(){
company::MyPrivateClass m;
}

MyPublicClass tem uma ligação externa e tem uma ligação interna. Então não há problema com source1 e ele pode ser compilado como uma biblioteca, mas se tivermos outro arquivo chamado source2.cpp:

//source2.cpp
void f2(){
company::MyPrivateClass m;
}

source2 não pode ser. ligado com o compilado source1 e não podemos referir-nos a MyPrivateClass.

 3
Author: rahnema1, 2018-01-27 06:15:48