1. Not finding help here? Sign up for a free 30min tutor trial with Chegg Tutors
    Dismiss Notice
Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

How do you access a pointer of a class nested in another class

  1. Mar 16, 2012 #1
    Given the following:
    Code (Text):
     class pairList {
      private:
        int value1, value2;
        pairList *nextEntry
        pairList *reverseM(pairList *prev);
      public:
        pairList(int v1, int v2, pairList *next) : value1(v1), value2(v2), nextEntry(next) {}
        int getFirstValue() { return value1; }
        int fetSecondValue() { return vlaue2; }
        pairList *getNextEntry() { return nextEntry; }
        pairList *reverseM();
        pairList *search(int val);
    };

     class grades {
      private:
         pairList *allGrades;
         float mean, stdDev;
         bool meanValue;
       public:
         grades() {}  // start with empty class
         void addGrade(int studentID, int grade);
         float average();
         int getScore(int studenID);
         int getZScore(int studentID);
         pairList *getAllGrades() { return allGrades; } // I added this line
    };
     
    My effort to access pairList within the grades class
    Code (Text):
     void grades::addGrade(int studentID, int grade)
     {
       grades *access = this;
       
       if(access->getAllGrades()->getNextEntry() != NULL)
         access->addGrade(studentID, grade);
       else
         access->getAllGrades()-getNextEntry() =
           new pairList(studentID, grade, NULL);   // I get an invallid lvalue in assignment here
     }

     pairList *readForwardList() {
      int inputval1, inputval2;
      pairList *front = NULL;
     
      cout << "enter ID no: " ; cin >> inputval1;
      cout << "\nEnter grade: "; cin >> inputval2;

      while(!cin.eof()) {
        front = new pairList(inputval1, inputval2, front);
        cout << "Enter ID no: ";  cin >> inputval1;
        cout << "\nEnter grade: "  cin >> inputval2;
       }
       cout '\n';
       return front->reverseM();
     }
     
    You cannot really create a local single linked pairList with readForwardList() and yet still be an automatic member of the outer class grades, I certainly don't think? That is, how do you do it, because the *allGrades pointer is private to the class grades. And any time you place it on the l.h.s. of an assignment you get an lvalue error, using getAllGrades().
    Code (Text):

      int main() {
        grades *theGrades, *tmpGrades;
        int i, j;

         theGrades->gatAllGrades() = readFowardList(); // error here! how do you do it correctly?
         tmpGrades = theGrades;
         while(tmpGrades->getAllGrades() != NULL) {
            i = tmpGrades->getAllGrades()->getFirstValue():
            j = tmpGrades->getAllGrades()->getSecondValue();
           cout << i << ' ' << j << ' ';
           tmpGrades->getAllGrades() = tmpGrades->getAllGrades()->getNextEntry();  // error, lvalue
        }
        cout '\n';
       // delete here
     return 0;
     }
     
    If you can see the problem I have, help is very welcome. Thanks in advance.
     
  2. jcsd
  3. Mar 18, 2012 #2
    I'm not sure I completely understand what you're being asked to do here. You said you added the getAllGrades() function, so does that mean everything else was given to you? And the goal is to implement the addGrade() function, or something else?

    If so, then is addGrade() allowed to put the new grade at the beginning of the list, or does it have to be at the end? If it's allowed to be at the beginning, then you ought to be able to just create a new pairList whose 'next' member points to allGrades, and then replace allGrades with your new pairList. You don't need a special accessor for that member, since you're accessing it from within the class.

    Once that's done, you should be able to implement readForwardList() by simply calling addGrade() repeatedly.
     
  4. Mar 18, 2012 #3

    rcgldr

    User Avatar
    Homework Helper

    Sometimes we all look for something complicated when it's just a simple bug. You used "-" instead of "->" for the pointer to getNextEntry(), it should be:

    Code (Text):

         access->getAllGrades()->getNextEntry() =
           new pairList(studentID, grade, NULL);   // I get an invallid lvalue in assignment here
     
     
  5. Mar 18, 2012 #4
    That's still going to give an lvalue error--you can't assign to the return value of a function like that. This code has some more fundamental problems than just a few typos.
     
  6. Mar 18, 2012 #5

    rcgldr

    User Avatar
    Homework Helper

    Getting back to the original question:
    You either make the pointer public, or create a function to set the pointer.

    I made the silly mistake this time. Wasn't paying attention to the fact that getNextEntry() was a function. Seems that adding an appendtoList() or setNextEntry() function in the intList class will be needed, or as already suggested, inserting new grades to the beginning of the list as was done with the other intList example programs. Example addList(), and example usage based on previous threads using class intList:

    Code (Text):

    intList *intList::addList(intList * newList){
        if(this == NULL){                   // if current list is empty
            return(newList);                //   return newList
        }
        intList *tmpList = this;            // append newList to this list
        while(tmpList->nextEntry != NULL)
            tmpList = tmpList->nextEntry;
        tmpList->nextEntry = newList;
        return(this);
    }

    int main(){
    using namespace std;
    intList *theList = NULL;
    int i;

        for(i = 0; i < 8; i++)              // initialize list {0..7}
            theList = theList->addList(new intList(i, NULL));
     
     
    Last edited: Mar 18, 2012
  7. Mar 18, 2012 #6
    Hi, Thanks for the replies. The question is: Define a new class, pairList which is like intList except that each cell contains two integers instead of one. Its operations are the same as intList, except that getValue() is replaced with getFirstValue() and getSecondValue(), and its constructor is also changed approppriately. Define the operation pairList *search(int val), which looks for a cell that has val as its first and returns a pointer to that cell.
    Using 'pairList' define the class grades that keeps a grade list, consisting of student ID numbers (integres) and grades on one exam, and reports grades in terms of z-scores.
    'mean' and 'stdDev' hold the mean and standard deviation of the scores but should not be computed each time a new grade is added. Instead, compute them only when one of the functions 'average', 'standardDeviation' or 'getZScores' is called. Set 'meanValid' to true when 'mean' and 'stdDev' are valid, and to false when they may not be.
    What I 'm asking is, for example, if I had the following :
    Code (Text):
     struct addr {
      char name[30];
      char street[40];
      char state[3];
      unsigned long int zip;
     }
    And I also have:
    Code (Text):
     
      struct emp {
        struct addr address;  // nested structre
        float wage;
     } worker;
    The following code assigns 12345 t0 the 'zip' element of "address"
    worker.address.zip = 12345;
    Can I not do something similar with pairList's elements given pairList *allGrades is a pointer of member of 'grades'. I don't think I can as no instance of pairList is defined in grades only a pointer to pairList, (as well as the member allGrades being private and not public; So I don't know where to start? I had tried making both nextEntry in pairList and allGrades public, but then I got a run time segmentation fault, and that is not the question anyway. The question assumes that it can be done the way itis setup.
     
  8. Mar 18, 2012 #7

    rcgldr

    User Avatar
    Homework Helper

    For addGrade() use Chopin's suggestion and insert new entries at the start of the list using the pairList constructor (which is public):

    Code (Text):

    grades::addGrade((int studentID, int grade){
        allGrades = new pairList(studentID, grade, allGrades);
    }
     
    grades default constructor needs to initalize it's members:

    Code (Text):

    class grades {
    // ...
         grades() {allGrades = NULL; mean = 0.; stdDev = 0.; meanValue = 0;}
    // ...
     
    I'm wondering why is meanValue a bool? What is meanValue used for?

    That will allow the grades class to implement a search by id function and return a pointer to that node in grade's pairList.

    In the case of a struct, the default is all members are public unless declared private. I don't think you need to change this. The segmentation fault in your test code mostly likely happened to infinite recursion and stack overflow. I don't think you need to use that code for this book's example, but if you'd like to fix it, post that example here or create a new thread to get that issue solved.
     
    Last edited: Mar 18, 2012
  9. Mar 18, 2012 #8
    Hi. Thanks for helping. In the grades constructor: grades() { } // start with empty lists, that is all he says. meanValue is set true when mean and stdDev are valid otherwise false. Because you are only to compute mean and stdDev each time average() , standardDeviation() and getZScore() is called They are not to be computed each time a new grade is added.
    No, I will not use the struct code example because I didn't even keep the code with the segmentation fault, I was just experimenting at the time. Thanks for the offer to look at it , though. I thought the question a bit open ended too.
     
  10. Mar 18, 2012 #9

    rcgldr

    User Avatar
    Homework Helper

    On my system, if my program (in debug mode) does a new, all members get set to 0xcdcdcdcd if the members aren't specifically initialized in the constructor, so they should be initialized in the constructor as I mentioned in my previous post, except meanValue could be set to false instead of 0.

    This could use a better name, like validValues.
     
  11. Mar 19, 2012 #10
    I replaced in the above readForwardList(): front = new pairList(inputval1, inputval2, front); with theGrade->addGrade(inputval1, inputval2); where theGrade is a pointer to grades, and where addGrade() is defined as in post #7. The program compiled fine, but when I ran it I got a segmentation fault on entering the first line of data.
     
  12. Mar 19, 2012 #11

    rcgldr

    User Avatar
    Homework Helper

    I suspect an issue with how you're handling cin.eof(). It would help if you got access to a source level debugger. If you're running some version of windows, then I would recommend microsoft visual c++ express, which is free. Can you show the actual code for readForwardList()?

    Also shouldn't the name of readForwardList() be something like inputGrades()?
     
  13. Mar 19, 2012 #12
    It is ok I got it working; I changed the initialization of the grades constructor from: grades() {allGrades = NULL; meanValue = false; } to, grades() : allGrades(NULL) { meanValue = false; }. Thanks, very much for helping all along.
     
  14. Mar 19, 2012 #13

    rcgldr

    User Avatar
    Homework Helper

    Are you sure you didn't use grades(){allGrades == NULL; meanValue = false;} (== instead of =)? This is working for me. Also I added a destructor to delete all the allocated pariLists in allGrades:

    Code (Text):

    class grades {
      private:
        pairList *allGrades;               // list of grades
        float mean, stdDev;
        bool meanValue;
      public:
        grades(){allGrades = NULL; meanValue = false;}
        ~grades();                         // destructor
        void addGrade(int studentID, int grade);
        void reverseM(){allGrades = allGrades->reverseM();}
        void showGrades();
    };

    grades::~grades(){
    pairList *tmpList;
        while(allGrades != NULL){
            tmpList = allGrades;
            allGrades = allGrades->getNextEntry();
            delete tmpList;
        }
    }
     
     
  15. Mar 19, 2012 #14
    OK, What I have done now is use a global pointer to grades (so that the average(), getZScore(), etc can access the input data) and now again, I am getting a segmentation fault. I have replaced readForwardList() with inputGrades().
    Code (Text):
     grades *theSubject = NULL; // global scope
    ....
    void inputGrades()
    {
       int inputval1, inputval2;
       // grades theSubject;  local scope

         cout << "Enter studentID no: ";  cin >> inputval1;
         cout << "Enter grade: ";  cin >> inputval2;

          while (!cin.eof()) {
            theSubject->addGrade(inputval1, inputval2);
            cout << "Enter studentID no: ";  cin >> inputval1;
            cout << "Enter grade: ";  cin >> inputval2;
          }
         cout << '\n';
     }

     int main()
     {
        //grades *theSubject;  local scope

        inputGrades();

       // mean();

       // deleteList(theSubject->getAllGrades());
    return 0;
     }
     
    When the pointer 'theSubject' is local scope the program inputs the values fine. But not when 'theSubject' is global. Thanks.
     
  16. Mar 19, 2012 #15
    No, I am sure of that. The book has not introduced us to destructors yet, infact another 10 pages has to go before before the book talks about delete. Thanks.
     
  17. Mar 19, 2012 #16

    rcgldr

    User Avatar
    Homework Helper

    You need to allocate an instance of grades:

    Code (Text):

    grades *theSubject = NULL;

    int main()
    {
    // ...
        theSubject = new grades;
    // ...
        theSubject->addGrade(...);
    // ...
    }
     
    or declare an actual instance of grades, but in this case it will be an instance of grades versus a pointer to grades:

    Code (Text):

    grades theSubject;

    int main()
    {
    // ...
        theSubject.addGrade(...);
    // ...
    }
     
    Since it's working for me, you could try this again. In C++, these two statements peform the same operation:

    Code (Text):

    pariList * allGrades(NULL);
    pairList * allGrades = NULL;
     
     
    Last edited: Mar 20, 2012
  18. Mar 20, 2012 #17
    It is working fine now. The lack of an instance of grades was the problem,I guess. I thought I had allGrades initialized the way I said I had, I actually had the initialization of allGrades left out altogether. Thank you for your time and going to the trouble of typing the program into your own computer. Thanks again.
     
  19. Mar 20, 2012 #18

    rcgldr

    User Avatar
    Homework Helper

    No problem, as I said, I was learning from this as well, as I haven't done that much with classes or the "this" pointer.
     
  20. Mar 20, 2012 #19
    Thanks very much. That was the problem as regards not having defined an instance of grades. In regard to the initialization of allGrades I hadn't initialized it at all, although I thought I had. The program works fine with with either initialization type.
    Thanks for taking the time and effort of typing in the program into your computer and getting it to work.
     
  21. Mar 20, 2012 #20

    rcgldr

    User Avatar
    Homework Helper

    I think you already created a delete list function to delete all the allGrades pairList elements. If so, you could make this part of the destructor (grades::~grades()); when you get to that part of the book. This will need to be public so your main program can delete an instance of grades.
     
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook




Similar Discussions: How do you access a pointer of a class nested in another class
Loading...