1

Possible Duplicate:
Can inner classes access private variables?
Inner class accessing outer class

I have some simple classes nested so they can interact with a variable without extra inputs, yet my compiler gives me an error. How would I allow for them to interact without using &time as function input or having the variable &time inside of the Vect class?

I tried using the same logic where you can have data accessed that is just in the code, at the same place as function prototypes, but is instead wrapped in a class. This works fine for anything I've used except other classes. Can anyone explain why?

I have marked the places that use the problematic time variable with comment lines like the one before the define.

/*********/
#define MAX_POLY 3

class Container
{
public:
    Container(void);
    ~Container(void);

    float time;/*********/
    class Vect
    {
        float P[MAX_POLY],iT;
    public:
        Vect(void){iT = 0.0f;P = {0,0,0};}
        ~Vect(void);

        float GetPoly(int n){return P[n];}
        float Render(void)
        {
            float t = time - iT;/*********/
            float temp[2] = {0,0};
            for(int n=0;n<MAX_POLY;n++)
            {
                temp[0] = P[n];
                for(int m=0;m<n;m++)
                    temp[0] *= t;
                temp[1] += temp[0];
            }
            return temp[1];
        }
        void SetPoly(int n,float f)
        {
            float t = time-iT;/*********/
            P[0] = P[2]*t*t + P[1]*t + P[0];
            P[1] = 2*P[2]*t + P[1];
            //P[2] = P[2];
            P[n] = f;
            iT = time;/*********/
        }
    }X;
};

int main()
{
    Container Shell;
    Shell.X.SetPoly(0,5);
    Shell.X.SetPoly(1,10);
    Shell.X.SetPoly(2,-1);
    for(int n=0;n<10;n++)
    {
        Shell.time = (float)n;
        cout << n << " " << Shell.X.Render() << endl;
    }
    system("pause");
    return 0;
}
Community
  • 1
  • 1
Joe Kessler
  • 51
  • 1
  • 1
  • 4

4 Answers4

4

The reason you get an error (I managed to figure it out even though you didn't post the actual error, please do that in the future), is that you actually don't have an instance of the Container class inside the functions of the Vect class. You should probably think about the design here, but to solve it quickly (and "dirty") you could add a function which sets a Container instance in the sub-class:

class Container
{
    ...

    class Vect
    {
        Container *container;

    public:
        void SetContainer(Container &container)
            { this->container = &container; }

        float Render(void)
            {
                float T = container->time - iT;
                ...
            }

        ...
    } X;
};

int main()
{
    Container Shell;
    Shell.X.SetContainer(Shell);
    Shell.X.SetPoly(0,5);
    ...
}

Edit: A better way is to set a reference to the parent object (thanks to juanchopanza for the idea) using the constructors:

class Container
{
    ...

    Container()
        : X(*this)
        { ... }

    class Vect
    {
        Container& container;

    public:
        Vect(Container& cont)
            : container(cont)
            { }

        float Render(void)
            {
                float T = container.time - iT;
                ...
            }

        ...
    } X;
};

I still think it's kind of a dirty solution (but not as dirty as my first), and that you should think about changing the design instead.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • I attempting to avoid using additional data for access calling, but I guess this is something I can't avoid, so Ill write an access function for it. Thanks for the help! – Joe Kessler Nov 09 '12 at 07:35
  • @JoeKessler probably better for the nested class to hold a reference to the parent, and initialize it in its constructor initialization list, since it doesn't make sense for the nested class to have no parent. – juanchopanza Nov 09 '12 at 07:47
  • @JoeKessler Added how to use the idea from juanchopanza. It's cleaner and less "dirty". – Some programmer dude Nov 09 '12 at 08:09
2

"...The members of a nested class have no special access to members of an enclosing class, nor to classes or functions that have granted friendship to an enclosing class; the usual access rules (clause 11) shall be obeyed. The members of an enclosing class have no special access to member of a nested class; the usual access rules(clause 11) shall be obeyed. ..."

Thus, make them friends.

John
  • 143
  • 1
  • 2
  • 12
2

The inner class cannot access the non-static variables of the outer class. This is C++ and we must instantiate the object before using it's non-static member data. So if you want to use your design, you have two choices:

  1. Change the variable (time in your case) to static. But you only have one copy of time for all Container classes.

  2. Have the nested class to contain a pointer to the parent class. The following code is similar to Joachim's solution, but we don't need to set the parent explicitly.

class Container {

    public:
      Container() : X(this) {}
      float time;

      class Vect {
      public:
        Vect(Container* parent) : parent_(parent) {}
        void foo() {
          myT = parent->time;
        }
      private:
        Container * parent_;
      } X;
    };
A.L
  • 10,259
  • 10
  • 67
  • 98
ozox
  • 472
  • 2
  • 11
0

Most basically, Classes are peer to classes. In OOPs principle each class is encapsulated. So how an inner class access another class' members directly. It violates basic principles of OOP.

dkumar
  • 33
  • 4