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

  • Thread starter John O' Meara
  • Start date
  • Tags
    Class
In summary: Main program intList *list1 = new intList; list1->addList( new intList(1, // Create a list of 3 elements new intList(2, new intList(3, NULL))));In summary, the given code contains two classes: pairList and grades. The pairList class is a single linked list that stores pairs of values and has functions for reversing the list and searching for a specific value. The grades class is used to store and manipulate a list of grades, using the pairList class to store the grades. The conversation discusses how to access the pairList within the grades class, with the suggestion of creating a function to set the pointer or inserting
  • #1
John O' Meara
330
0
Given the following:
Code:
 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:
 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:
  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.
 
Physics news on Phys.org
  • #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.
 
  • #3
John O' Meara said:
Given the following:
Code:
     access->getAllGrades()-getNextEntry() =
       new pairList(studentID, grade, NULL);   // I get an invallid lvalue in assignment here
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:
     access->getAllGrades()->getNextEntry() =
       new pairList(studentID, grade, NULL);   // I get an invallid lvalue in assignment here
 
  • #4
rcgldr said:
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:
     access->getAllGrades()->getNextEntry() =
       new pairList(studentID, grade, NULL);   // I get an invallid lvalue in assignment here

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.
 
  • #5
Getting back to the original question:
John O' Meara said:
How do you access a pointer of a class nested in another class?
You either make the pointer public, or create a function to set the pointer.

rcgldr said:
Code:
     access->getAllGrades()->getNextEntry() =
       new pairList(studentID, grade, NULL);

Chopin said:
That's still going to give an lvalue error--you can't assign to the return value of a function like that.
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:
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:
  • #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:
 struct addr {
  char name[30];
  char street[40];
  char state[3];
  unsigned long int zip;
 }
And I also have:
Code:
  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.
 
  • #7
John O' Meara said:
... addGrade() ...
For addGrade() use Chopin's suggestion and insert new entries at the start of the list using the pairList constructor (which is public):

Code:
grades::addGrade((int studentID, int grade){
    allGrades = new pairList(studentID, grade, allGrades);
}

grades default constructor needs to initalize it's members:

Code:
class grades {
// ...
     grades() {allGrades = NULL; mean = 0.; stdDev = 0.; meanValue = 0;}
// ...

I'm wondering why is meanValue a bool? What is meanValue used for?

John O' Meara said:
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.
That will allow the grades class to implement a search by id function and return a pointer to that node in grade's pairList.

John O' Meara said:
If I had the following " ... struct ... ".
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:
  • #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.
 
  • #9
John O' Meara said:
In the grades constructor: grades() { } // start with empty lists, that is all he says.
On my system, if my program (in debug mode) does a new, all members get set to 0xcblackd 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.

John O' Meara said:
meanValue
This could use a better name, like validValues.
 
  • #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.
 
  • #11
John O' Meara said:
got a segmentation fault on entering the first line of data.
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()?
 
  • #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.
 
  • #13
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:
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;
    }
}
 
  • #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:
 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.
 
  • #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.
 
  • #16
John O' Meara said:
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().
You need to allocate an instance of grades:

Code:
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:
grades theSubject;

int main()
{
// ...
    theSubject.addGrade(...);
// ...
}

rcgldr said:
Are you sure you didn't use grades(){allGrades == NULL; meanValue = false;} (== instead of =)? This is working for me.

John O' Meara said:
No, I am sure of that.
Since it's working for me, you could try this again. In C++, these two statements peform the same operation:

Code:
pariList * allGrades(NULL);
pairList * allGrades = NULL;
 
Last edited:
  • #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.
 
  • #18
John O' Meara said:
Thank you for your time.
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.
 
  • #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.
 
  • #20
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.
 

1. How do you access a pointer of a class nested in another class?

To access a pointer of a class nested in another class, you can use the scope resolution operator (::) to specify the outer class, followed by the inner class name, and then the pointer name. For example, if the outer class is called OuterClass and the inner class is called InnerClass, you can access the pointer using OuterClass::InnerClass::pointerName.

2. Can you use a pointer to access a nested class directly?

No, you cannot use a pointer to access a nested class directly. You can only use a pointer to access the members and functions of the nested class.

3. How do you declare a pointer to a nested class?

To declare a pointer to a nested class, you can use the same syntax as declaring a pointer to a regular class. For example, if the nested class is called InnerClass, you can declare a pointer using InnerClass* pointerName.

4. How do you initialize a pointer to a nested class?

To initialize a pointer to a nested class, you can use the new keyword followed by the nested class name, and then assign it to the pointer. For example, if the nested class is called InnerClass, you can initialize the pointer using pointerName = new InnerClass().

5. How do you access the members and functions of a nested class using a pointer?

To access the members and functions of a nested class using a pointer, you can use the arrow operator (->) to dereference the pointer and access the desired member or function. For example, if you have a pointer to a nested class called pointerName and you want to access a member variable called myVariable, you can use pointerName->myVariable.

Similar threads

  • Programming and Computer Science
Replies
1
Views
1K
  • Programming and Computer Science
Replies
6
Views
2K
Back
Top