views:

679

answers:

4

This is a question about what defining a class as public or private does.

Right now, I have various classes defined inside of a namespace and I only want some of those classes to be visible/usable to the outside world.

So, for example, if the classes below were the only ones in the program, I would want main.cpp to only be able to see/use the MyPublic class, not the MyPrivate class. I thought that defining the MyPrivate class as private and the MyPublic class as public would accomplish this, but the below code works and main.cpp is able to declare a MyPrivate object.

Is it possible to do this in C++?

MyPrivate.h:

namespace MyNamespace{

    // only classes inside of the MyNamespace should be able
    // to use this
    private ref class MyPrivate{
        ...
    };
}

MyPublic.h:

#include "MyPrivate.h"

namespace MyNamespace {

    // anyone can declare this
    public ref class MyPublic{
        ...
        private:
            MyNamespace::MyPrivate^ p;
        ...
    };
}

Main.cpp:

#include "MyPublic.h"

int main(){

    MyNamespace::MyPublic p_yes; // this is fine    
    MyNamespace::MyPrivate p_no; // don't want this to be possible

    return 0;
}
+3  A: 

private/public in this situation will affect how classes are visible outside an assembly, if you want to create a class that is "private" in the meaning that it can be used only by some other class, you can use nested clas mechanism, like this:

namespace MyNamespace {
    public ref class MyPublic {
       private:

           ref class MyPrivate {
               public:
               int x;
           };

           MyPrivate^ p;
    };
}

//Edit: You can by the way still throw this nested class in public: section and use it like this:
MyNamespace::MyPublic::MyPrivate priv;

Ravadre
A: 

You public header shouldn't include private header. Forward declare private class and include header only in MyPublic.cpp. Or that's what I'd say if you used normal C++. Bastardized .Net dialect might change things.

Eugene
A: 

Unfortunately, the access modifiers on a class only affect visibility outside the assembly you're building. C++ doesn't support any sort of access modifiers that apply to namespaces in the way you're describing.

A common idiom for simulating this is to put the "private" code into a detail namespace (e.g. put it in MyNamespace::detail). This is used a lot in e.g. the boost libraries. By convention, code in a detail namespace should only be used by code in the enclosing namespace (so MyNamespace::detail should only be used by code in MyNamespace), although the compiler won't enforce this for you.

Charlie
+1  A: 

The private keyword means something else than you think. I limits visibility of the ref class beyond the assembly. Since your Main() method is in the same assembly, it has no trouble referencing the type name. Note that the C# language's "internal" keyword means the same thing.

I assume that you really intend for these classes to be in a separate assembly someday. As such, using private is certainly good enough. Using nested private classes can make a class inaccessible to code in the same assembly.

Hans Passant