151
class Outer {

    class Inner {
    public:
        Inner() {}
        void func() ;
    };

private:
    static const char* const MYCONST;
    int var;
};

void Outer::Inner::func() {
    var = 1;
}

const char* const Outer::MYCONST = "myconst";

This errors out when I compile with class Outer::Inner' has no member named `var'

Community
  • 1
  • 1
kal
  • 28,545
  • 49
  • 129
  • 149

5 Answers5

160

An inner class is a friend of the class it is defined within.
So, yes; an object of type Outer::Inner can access the member variable var of an object of type Outer.

Unlike Java though, there is no correlation between an object of type Outer::Inner and an object of the parent class. You have to make the parent child relationship manually.

#include <string>
#include <iostream>

class Outer
{
    class Inner
    {
        public:
            Inner(Outer& x): parent(x) {}
            void func()
            {
                std::string a = "myconst1";
                std::cout << parent.var << std::endl;

                if (a == MYCONST)
                {   std::cout << "string same" << std::endl;
                }
                else
                {   std::cout << "string not same" << std::endl;
                }
            }
        private:
            Outer&  parent;
    };

    public:
        Outer()
            :i(*this)
            ,var(4)
        {}
        Outer(Outer& other)
            :i(other)
            ,var(22)
        {}
        void func()
        {
            i.func();
        }
    private:
        static const char* const MYCONST;
        Inner i;
        int var;
};

const char* const Outer::MYCONST = "myconst";

int main()
{

    Outer           o1;
    Outer           o2(o1);
    o1.func();
    o2.func();
}
SimplyKnownAsG
  • 904
  • 9
  • 26
Martin York
  • 257,169
  • 86
  • 333
  • 562
  • 16
    Technically in the current C++ standard, a nested class does NOT have special access to its enclosing class. See sec 11.8.1 of the standard. HOWEVER see also this standard defect: http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#45 – Greg Rogers Mar 09 '09 at 20:13
  • 2
    For what its worth, GCC follows the proposed resolution given there, other compilers probably do too. – Greg Rogers Mar 09 '09 at 20:13
  • 29
    The C+11 standard is now compliant with the above description. – Martin York Apr 23 '13 at 21:20
  • 1
    In Java, non-static inner class is implicitly given a reference (pointer) to the instance of its outer class when the inner class is first accessed. To rephrase this, jvm is implicitly writing a code for you that is similar to what @LokiAstari shown us in his answer. Here's an excerpt from [Effective Java 2nd Ed](http://www.amazon.com/Effective-Java-Edition-Joshua-Bloch/dp/0321356683) "Item 22: Favor static member classes over nonstatic": "If you omit this modifier (static keyword when declaring inner class), each instance will have an extraneous reference to its enclosing instance". – David Lee Jul 01 '14 at 16:28
  • This creates serious copy/move issues for Outer objects. In the example code, the Inner object is constructed anew every time the Outer object is copied. At least it's correct. See http://stackoverflow.com/questions/12849013 for an accepted answer with code that leaves dangling references. – Brent Baccala Jan 20 '16 at 03:49
  • @BrentBaccala: The point of the above is to show exactly that. I am trying to show that the semantics of C++ does not match those of Java. Just because you have an inner class with a reference to the outer class does not mean it is the same outer class as the object that owns it and that can be an issue. – Martin York Jan 20 '16 at 06:26
  • @Loki Astari: Actually, is it correct? Doesn't the copy constuctor, as written, leave the copy with a reference pointing back to the original? I ran it - "4" gets printed twice. – Brent Baccala Jan 20 '16 at 08:56
  • @BrentBaccala: That's the point!!!! Its supposed to be broken. As explained in the answer and the last comment, An inner class in C++ is not like an inner class in Java – Martin York Jan 20 '16 at 09:56
  • 4
    @Loki Astari: I read the last sentence "You have to make the parent child relationship manually" and interpreted the code fragment that followed as an example of how to do that _correctly_! – Brent Baccala Jan 20 '16 at 22:01
  • @BrentBaccala: `Unlike Java though, there is no correlation between` – Martin York Jan 20 '16 at 22:21
38

An inner class has access to all members of the outer class, but it does not have an implicit reference to a parent class instance (unlike some weirdness with Java). So if you pass a reference to the outer class to the inner class, it can reference anything in the outer class instance.

MSN
  • 53,214
  • 7
  • 75
  • 105
8

Anything that is part of Outer should have access to all of Outer's members, public or private.

Edit: your compiler is correct, var is not a member of Inner. But if you have a reference or pointer to an instance of Outer, it could access that.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
4

First of all, you are trying to access non-static member var outside the class which is not allowed in C++.

Mark's answer is correct.

Anything that is part of Outer should have access to all of Outer's members, public or private.

So you can do two things, either declare var as static or use a reference of an instance of the outer class to access 'var' (because a friend class or function also needs reference to access private data).

Static var

Change var to static If you don't want var to be associated with the instances of the class.

#include <iostream>

class Outer {

private:
    static const char* const MYCONST;
    static int var;

public:
   class Inner {
    public:
        Inner() {
          Outer::var = 1;
        }
        void func() ;
    };
};

int Outer::var = 0;

void Outer::Inner::func() {
    std::cout << "var: "<< Outer::var;
}

int main() {
  Outer outer;
  Outer::Inner inner;
  inner.func();

}

Output- var: 1

Non-static var

An object's reference is a must to access any non-static member variables.

#include <iostream>

class Outer {

private:
    static const char* const MYCONST;
    int var;

public:
   class Inner {
    public:
        Inner(Outer &outer) {
          outer.var = 1;
        }
        void func(const Outer &outer) ;
    };
};

void Outer::Inner::func(const Outer &outer) {
    std::cout << "var: "<< outer.var;
}

int main() {
  Outer outer;
  Outer::Inner inner(outer);
  inner.func(outer);

}

Output- var: 1

Edit - External links are links to my Blog.

Adarsh Kumar
  • 467
  • 6
  • 11
2

var is not a member of inner class.

To access var, a pointer or reference to an outer class instance should be used. e.g. pOuter->var will work if the inner class is a friend of outer, or, var is public, if one follows C++ standard strictly.

Some compilers treat inner classes as the friend of the outer, but some may not. See this document for IBM compiler:

"A nested class is declared within the scope of another class. The name of a nested class is local to its enclosing class. Unless you use explicit pointers, references, or object names, declarations in a nested class can only use visible constructs, including type names, static members, and enumerators from the enclosing class and global variables.

Member functions of a nested class follow regular access rules and have no special access privileges to members of their enclosing classes. Member functions of the enclosing class have no special access to members of a nested class."

xiaochuanQ
  • 190
  • 5
  • 4
    Wrong. See other answers - 3 years earlier. "if one follows C++ standard strictly", they reach different answers from yours. As of an early draft for C++11, nested classes can access _all_ members of the parent via a reference/pointer. There is no requirement to explicitly declare `friend` or `public`. Who cares if IBM were wrong/outdated, in the past, at a dead link? This answer was already out of date 3 years before it was posted. – underscore_d Dec 04 '15 at 20:26