Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a static nested class in C++ like Java?

Tags:

c++

I'm regular to write in java, and I'm a little bit confused about static nested class in C++.

I'm trying to declare a static class, but I get an error :

class D
{
    public:

    static class Listener
    {
        public :

        void foo()
        {
            cout << "foo" <<endl;
        }
    };

};

And I getting following error

"storage class can only be specified for objects and functions"

(I'm using an online compiler).

like image 620
I.Mac Avatar asked Dec 17 '16 10:12

I.Mac


2 Answers

The correct terminology would be "static nested class".

Static nested classes in Java are like normal nested classes in C++, so just drop the static and it should work fine.

Non-static ones like in Java would be a bit harder to emulate in C++, because there is no compiler magic to automatically provide the context of the outer class. You would have to work around the issue by storing a reference to the outer class in the inner class, initialising it in the constructor of the inner class, and accessing members of the outer class explicitly via the reference.

like image 107
Christian Hackl Avatar answered Nov 03 '22 11:11

Christian Hackl


Classes in C++ are merely nested type definitions, so only act as namespaces for nested type definitions.

If you declared a class type definition as static anywhere (nested or not nested), you'd get a compiler warning and it will be stripped off. Classes cannot have storage class specifiers and static has been repurposed something different inside a class. This is because class types don't have storage at all and are just templates (so linkage doesn't make sense; they don't even survive that far), and method definitions are compiler directives that the compiler is able to concretise when it chooses, but just so easily can exclude from the assembly output, unlike regular functions, which are guaranteed to be present when placed in another translation unit, so all class members are effectively inline (unless static, then they need to be explicitly made inline to provide an inline definition). static used on a class inside a class is redundant because classes nested are implicitly static in this sense.

When you instantiate the parent class, it does not include the nested class because this is just a compiler directive. You have to include an object of the class as one of the members, where the class type definition is in scope:

class c {
  public :
  int i;
  class s f; //not allowed
  class s;
  class s k; //not allowed, still has forward declaration type
  class s {
    public:
    int j;    
  };
  s p; // allowed
};

You can forward declare a nested class in a class but a member cannot be defined with a forward declaration incomplete type unless it is a pointer or reference to it, but it can be with an incomplete type if the type has been completed above it in the scope.

Unlike a namespace however, you cannot access non-static members of the parent class from the nested class (this type of static and non-static do not exist in namespaces anyway). This is because the nested class is instantiated separately to the parent class and the parent class may never be instantiated. It just so happens that the programmer may initialise the nested object in the parent object, just as it could store it in a pointer in the object or a local pointer and initialise it on the heap, but at the object level, they are separate objects and where their type definitions are is irrelevant. If you called a non-static member of the parent class, the compiler would have to pass an object of the parent class to it. It could theoretically use the parent class type definition to determine the offset it will be at in memory for the member it fills, but it might not always be a subobject of a parent object. In order for this functionality to be allowed, the compiler would have to throw an error if the subclass is instantiated without the parent class being instantiated and it being assigned as a subobject of the parent subobject.

like image 41
Lewis Kelsey Avatar answered Nov 03 '22 12:11

Lewis Kelsey