Does C++ have anything like Java's inner classes?

I sometimes come across a situation where I want to create a class manages a list of records. The records themselves will never be used outside of the class, but I none the less need to declare the class in the header so that the compiler knows what size it is. It would be nice if I could 'hide' this extra class somehow so I'm not cluttering the namespace with a class that will not be used elsewhere.

Java lets you do things like this by using inner classes, but as far as I can tell C++ does not support this.

For example, is there a way so that only DogShow (which is accessible by the rest of the program) can use Dog without Dog also being accessible?

struct Dog
{
int _id;
QString _name;
QString _breed;
};

class DogShow
{
QMap<int, Dog> _dogs;
public:
void registerDog(int id, QString name, QString breed) {
Dog dog;
dog._id = id;
dog._name = name;
dog._breed = breed;
_dogs[id] = dog;
}

QString dogName(int id) {
return _dogs[id]._name;
}
};
You can use an anonymous namespace:

1
2
3
4
5
6
7
8
namespace {
    struct Dog
    {
        int _id;
        QString _name;
        QString _breed;
    };
}
C++ allows for inner classes as well.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// Example program
#include <iostream>
#include <string>

class DogShow
{       

  public:  
    void registerDog(int id, const std::string& name) {
        Dog dog;
        dog.id = id;
        dog.name = name;
        dogs[0] = dog;
        // etc. just example.
    }

  private:
    struct Dog
    {
        int id;
        std::string name;
    };
    
    Dog dogs[5];
};

int main()
{
    DogShow dogShow;
    dogShow.registerDog(12345, "Snowball");
    
    // DogShow::Dog dog; // error
}
You can use an anonymous namespace

Unnamed namespaces should normally not be used in header files. It does not prevent you from using Dog in files that includes the header, and it's too easily to run into ODR issues.
Last edited on
Ganado + 1

That said, the current idiomatic way to do stuff like that is to have a sub-namespace called “detail”. It does not prevent people from using it, but everyone knows it is synonymous with don’t touch.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
namespace kitfox
{
  namespace detail
  {
    struct Dog
    {
      …
    };
  } // detail

  class DogShow
  {
    private:
      QMap<int,detail::Dog> _dogs;

    public:
      …
  };

} // kitfox 

This particular example, however, does not sit right. The dog show is a collection of dogs that you are not allowed to see or touch.

The Dog itself may have opaque, do-not-touch parts to it, but the end user should still have at least a Dog token he can refer to when at the dog show.

(For example, a GUI may give you a Window, even if all you can do with that window is pass it around to various functions/methods/whatever.)

Hope this helps.
for what its worth, in my experience, as soon as you block something from being used outside its little sandbox, you discover that it sure would be useful somewhere else. Namespace is a great fix for that, as it does allow you to use it if you need it elsewhere, though it violates convention.
I prefer to just let it be usable. The only time I really avoid that is a singleton, and I avoid those too as much as possible.
Topic archived. No new replies allowed.