pointer to pointer

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Omega
    New Member
    • Oct 2007
    • 12

    pointer to pointer

    Hello,

    I'm working on a project with a couple of classes connected via aggregations like this:

    ClassA <>---1 ClassB <>---5 ClassC

    ClassC contains int value;

    Now ClassA declares ClassB as: ClassB* itsClassB
    And ClassB declares ClassC as: ClassC* itsClassC[5]

    Normally, I could get 'value' by using 'itsClassC[0]->getValue();' from within ClassB. But now I want it from within ClassA. My guess was to use 'itsClassB->itsClassC[0]->getValue();' but that doesn't seem to work.

    How do I correctly call the 'getValue()' operation from within ClassA?

    Thanks in advance
  • Banfa
    Recognized Expert Expert
    • Feb 2006
    • 9067

    #2
    Originally posted by Omega
    My guess was to use 'itsClassB->itsClassC[0]->getValue();' but that doesn't seem to work.
    That looks right to me

    "doesn't seem to work" == doesn't compile

    or

    "doesn't seem to work" == returns the wrong value when the program is running

    ?

    Comment

    • Omega
      New Member
      • Oct 2007
      • 12

      #3
      it doesn't compile. When I use the following trick it does compile. I create an extra operation 'getValue' in ClassB. 'getValue' in ClassB returns itsClassC[0]->getValue();

      So now I call from ClassA: itsClassB->getValue();

      The (first) error message that is generated when I use itsClassB->itsClassC[0]->getValue(); directly is:

      'itsClassC' : cannot access protected member declared in class 'ClassB'.

      I use a 'builder' class that creates the class structure and then I run 'init' operations in every class from top to bottom to allocate memory. So ClassA allocates memory for ClassB and ClassB allocates memory for classC, maybe that's the problem? But if it is, I don't see how to allocate all memory from ClassA, since it doesn't have a direct connection to ClassC.

      Comment

      • Banfa
        Recognized Expert Expert
        • Feb 2006
        • 9067

        #4
        Originally posted by Omega
        'itsClassC' : cannot access protected member declared in class 'ClassB'.
        The clue is in the error message. The memory allocation is not relevant to the problem.

        You have declared itsClassC as a protected (or may be private) member of ClassB. This means that only ClassB can access it. When you use
        [code=cpp]itsClassB->itsClassC[0]->getValue();[/code]from a method in class A you get the error because you are trying to access protected data of ClassB from ClassA.

        Implementing a GetValue in ClassB circumvents this because you then stop trying to access ClassB data from ClassA, each class just accesses it's own data. This is probably the correct solution, however there are other possibilities

        You could make itsClassC in ClassB public, then anyone can access it. Obviously this is not a good idea because it breaks the data encapsulation of ClassB.

        You could make ClassA a friend of ClassB, ClassA could then access ClassBs protected and private data. This may or may not be a good idea, it kind of depends how interrelated ClassA and ClassB are.


        However as I already said implementing a getValue in ClassB is probably the way to go.

        Comment

        • Omega
          New Member
          • Oct 2007
          • 12

          #5
          Okay, I see the problem (thanks). I didn't see it immediately because I use a graphical environment (Rhapsody) where a lot of code is generated.

          The problem isn't completely solved however, because the compiler doesn't know about the instance of ClassC when I call itsClassB->itsClassC[0]->getValue(); from ClassA:

          error: use of undefined type 'ClassC'

          That is caused by the fact that I only declare an instance of ClassB in ClassA. When the compiler checks the code of ClassA it finds a function that uses an instance of ClassC (which will be declared later...). Do you have a solution for this too?

          Comment

          • Omega
            New Member
            • Oct 2007
            • 12

            #6
            By the way, the reason that I want direct access to ClassC is that it is a kind of database structure from where I want to pick attributes. It's a bit more complex than the given example, since there is also a ClassD (and maybe more).
            If I use the 'getValue' function I would have the same problem with lowel level classes (that also have their attributes). So I'd rather want to use something like

            ClassB->ClassC[3]->ClassD[21]->getItem();

            Comment

            • Ganon11
              Recognized Expert Specialist
              • Oct 2006
              • 3651

              #7
              Are all these classes defined in separate header files (e.g. ClassA is in ClassA.h, ClassB is in ClassB.h, etc.)? If so, make sure you are #including them properly. ClassA should be able to know about the existence of ClassC if it is to work properly.

              Comment

              • weaknessforcats
                Recognized Expert Expert
                • Mar 2007
                • 9214

                #8
                Originally posted by Omega
                was to use 'itsClassB->itsClassC[0]->getValue();' but that doesn't seem to work.
                Your answer is right here in your quote and it is: Do not code this way.

                This is the old C-style spaghetti code that breaks encapsulation by exposing your implementation.

                Your correct code is:
                [code=cpp]
                A obj;
                cout << obj.getvalue(3) ; //fetchg the 3rd value
                [/code]

                and you are done.

                Assuming the value is an int. that means:
                [code=cpp]
                int A::getvalue(int arg)
                {

                }


                Now ClassA declares ClassB as: ClassB* itsClassB
                And ClassB declares ClassC as: ClassC* itsClassC[5]

                Comment

                • weaknessforcats
                  Recognized Expert Expert
                  • Mar 2007
                  • 9214

                  #9
                  Originally posted by Omega
                  was to use 'itsClassB->itsClassC[0]->getValue();' but that doesn't seem to work.
                  Your answer is right here in your quote and it is: Do not code this way.

                  This is the old C-style spaghetti code that breaks encapsulation by exposing your implementation. This drill-down approach produces a thread of code that breaks if you change class B or class C. The more code you break with a change the weaker the encapsulation.

                  Your correct code is:
                  [code=cpp]
                  A obj;
                  cout << obj.getvalue(3) ; //fetch the 3rd value
                  [/code]

                  and you are done.

                  Assuming the value is an int. that means:
                  [code=cpp]
                  int A::getvalue(int arg)
                  {
                  return b->getvalue(arg );
                  }
                  [/code]

                  where:
                  [code=cpp]
                  int B::getvalue(int arg)
                  {
                  return c->getvalue(arg );
                  }
                  [/code]

                  where
                  [code=cpp]
                  int C::getvalue(int arg)
                  {
                  return this->data[arg];
                  }
                  [/code]

                  Anytime you see code like a->b->c->d, a red flag should appear in front of you with the words: Wrong Way.

                  I know this is done all the time in C and it's still wrong. It's just sloppy.

                  Comment

                  • Omega
                    New Member
                    • Oct 2007
                    • 12

                    #10
                    It might be wrong, but the easiest way. ;)

                    I guess I have to get used to the way of writing c++ (indeed, I have more experience with C). But I managed to find a reasonable solution to my problem based on the first solution of getValue() in ClassB. (Every class in the series calls the following by a function and parameters).

                    Thanks everybody!

                    One more question that has to do with memory allocation;
                    When I declare ClassB from within ClassA I declare memory like;

                    itsClassB = (itsClassB*)mal loc(sizeof(Clas sB));

                    which works fine for attributes and so on. But when I want to call a function with an argument (e.g. getValue(int x); ) in ClassB it crashes... Somehow the memory declaration doesn't take care of arguments in parameters. Is there a way to declare memory for them or should I use pointers again?

                    Comment

                    • Banfa
                      Recognized Expert Expert
                      • Feb 2006
                      • 9067

                      #11
                      When using C++, particularly when allocating memory for objects you should always use the new operator.

                      new ensures that the constructor for the class is called where as malloc just returns enough memory to fit the object in. If the constructor is not called then the object is not initialised and the constructors for any objects it contains are not called either.

                      [code=cpp]
                      itsClassB = new ClassB;
                      [/code]

                      Comment

                      Working...