Is there a way to make a class visible only from within another class. i.e:

class myclass
{
private:
class anotherclass
{
    //stuff that only can be used from within a myclass function
    void dosomething();
    float dosomethingelse();
}*anotherclasses;
int numanotherclasses;
public:
int createanotherclass();//creates anotherclass object, puts it in the array and returns its index
void dosomething(int index);
float dosomethingelse(int index);
};

But in this example I would need to be unable to make an anotherclass from outside of myclass. Is this possible and if so what is the syntax for it?

The following works for me:

#include <iostream>
#include <vector>

class Outer {
    struct Inner {
        int i_;
        Inner(int i) : i_(i) {}
    };

    std::vector< Inner > vinner;

public:

    int construct (int i) {
        vinner.push_back (Inner(i));
        return vinner.size() - 1;
    }

    int get (int i) { return vinner[i].i_; }
};

int main () {

    Outer outer;
    outer.construct (10);
    outer.construct (20);
    outer.construct (30);
    outer.construct (40);

    // outputs '30'
    std::cout << outer.get (2) << std::endl;

    return 0;
}

In the above Outer::Inner is private and can not be constructed outside the scope of Outer What exactly are you trying to do that is not working the way you expect?

Edited 5 Years Ago by L7Sqr: n/a

>>But in this example I would need to be unable to make an anotherclass from outside of myclass. Is this possible and if so what is the syntax for it?

Well, the code that you showed, or that of L7Sqr, achieve exactly that. Another way is to create a separate class (not nested), make all its members private (including the constructors/destructor) and then make friendships to the selected few classes that should use that hidden class.

There are also other alternatives to "hide" a class. Often, you don't implement a complex class as just one class, it is often useful to break it up into helper classes. Now, since those helper classes are part of the "implementation details" of the containing class, you often want to hide them away from the user of your library. There are two very common practices to do so:

1) If you want your helper class to be hidden from the user but available for developing other classes in your library, then people often will use a "detail" namespace. By convention, anything that you find in the "detail" namespace of a library are things that you should not use unless you are developing things in that library. Here is how you generally do it:

// in "detail/my_helper.h":
#ifndef MYLIB_DETAIL_MY_HELPER_H
#define MYLIB_DETAIL_MY_HELPER_H

namespace my_library {  namespace detail {

class my_helper { 
  //...
};

}; };

#endif

//in "my_class.h":
#ifndef MYLIB_MY_CLASS_H
#define MYLIB_MY_CLASS_H

#include "detail/my_helper.h"

namespace my_library {

class my_class {
  private:
    detail::my_helper mHelper;
  //...
};

};
#endif

Of course, the above doesn't make it impossible for the user to create or use the detail::my_helper class, but, by convention, it is clear that it should not be used. Many libraries are built this way, the top-level namespace (e.g. std or boost ) contain only front-end classes that expose some well behaved, well documented and safe interfaces, but then, almost all the actual implementation is found under some sub-namespaces and detail-namespaces which actually contain classes and functions that less "user-friendly" but more adequate for structuring the code in a flexible manner. It is highly recommended to think about your library in terms of what is the "interface" and what are the "implementation details", because both have their own set of "good practices" rules, and both should be separated (often as main namespaces and detail namespaces).


2) If you want the class to be completely hidden from the user, you can use the "PImpl idiom" (or "Cheshire Cat", or "Compilation firewall"). The alternative names come from the fact that this idiom has other practical uses besides just hidden a helper class (e.g. it can isolate external dependencies to prevent code pollution / dependencies (i.e. "compilation firewall"), or it can solve binary compatibility issues (i.e. "Cheshire Cat") by trivializing the binary footprint). But, the basic use, as its basic name implies, is to have a pointer to an implementation object (idiomatically called "pImpl" or something similar). Here's how you do it (which you can use in complement to the above code):

//in "my_class.h":
#ifndef MYLIB_MY_CLASS_H
#define MYLIB_MY_CLASS_H

namespace my_library {

namespace detail {
class my_helper; //forward-declare a hidden helper class.
};

class my_class {
  private:
    detail::my_helper* pImpl; //hold a pointer to a helper object.

  public:
    my_class();
    ~my_class();
    void do_something(); 
   //...
};

};

#endif

//in "my_class.cpp":

#include "my_class.h"  //include the class' header file.

#include "detail/my_helper.h"  //include the helper class' header file (such that you can actually use it).

namespace my_library {

my_class::my_class() : pImpl( new detail::my_helper() ) { };

my_class::~my_class() { delete pImpl; };

void my_class::do_something() {
  pImpl->do_something();
};

};

The above entail a certain amount of overhead in the heap allocation and indirection, but it is mighty useful in many situations. The main advantage here is that the actual declaration, implementation, and additional dependencies of the helper class are completely isolated and hidden away from the user (as you would normally compile that cpp file into an object file or library (static or shared)). In many cases, if the project is not open-source, you wouldn't even ship the header file (or source) for the helper class because it is entirely unnecessary to the user.

Edited 5 Years Ago by mike_2000_17: n/a

This article has been dead for over six months. Start a new discussion instead.