#1
  1. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2003
    Posts
    154
    Rep Power
    14

    Re: problem initiating objects of class


    Can anyone please offer some advice what the following error message means:

    college.cc: In function `int main(int, char**)':
    college.cc:59: pointer to a function used in arithmetic
    college.cc:59: request for member `setName' in `*(pupilnames() + (+i))',
    which is of non-aggregate type `std::vector<Pupil, std::allocator<Pupil>
    > ()()'

    the lines in my program which this error occurs are:

    vector <Pupil> pupilnames(); // line 45

    string name; // line 47

    int i; // line 49

    while (!inFile.eof ()) // line 51
    { // line 52

    if (!inFile.fail ()) // line 54
    { // line 55

    inFile >> name; // line 57

    pupilnames[i].setName(name); // line 59

    i++; // line 61
    } // line 62
    } // line 63

    Hope this is enough to get an idea what the problem is!
  2. #2
  3. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,145
    Rep Power
    2222
    I learned my C++ pre-STL, so I'll ask a stupid question that might point you in the right direction.

    When you create a vector of objects, does that vector end up containing instances of that object, or does it contain pointers to instances of the object?

    In other words, should line 59 instead be:
    Code:
    pupilnames[i]->setName(name);
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2003
    Posts
    154
    Rep Power
    14
    My vector is supposed to create instances of the object rather than pointers and anyway even if I use pointers as in your code, I still get the error message shown on the previous post.
  6. #4
  7. not a fan of fascism (n00b)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Feb 2003
    Location
    ct
    Posts
    2,756
    Rep Power
    95
    try sticking std:: in front of vector when u declare one. i remember having similar problems on a project i worked on.
  8. #5
  9. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,145
    Rep Power
    2222
    Again, I don't have the experience with STL, but look at the second error message:

    college.cc:59: request for member `setName' in `*(pupilnames() + (+i))',
    which is of non-aggregate type `std::vector<Pupil, std::allocator<Pupil>
    > ()()'
    I assume that your Pupil class has been declared properly, so why does the compiler think that it is a non-agregate type?

    In Googling on this problem, I see other examples declaring the vector differently; eg:

    vector<int> v;
    What happens with you leave the parentheses out in line 45?

    vector <Pupil> pupilnames; // line 45
    // instead of vector <Pupil> pupilnames(); // line 45
    Had you created a vector of constructors by mistake? That could tie in with the error message complaining about a function pointer.

    Also, I anticipate that you will have a runtime error. I would think that the vector would be empty when first created and that you will need to instantiate a Pupil before you can call its SetName() method and add it to the vector either before or after the SetName(), which would affect how you write it.
  10. #6
  11. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2003
    Posts
    154
    Rep Power
    14
    Yes, your right it does appear that by removing the parenthesis, the error disappears. I've only had experience in using vectors of a pre-determined size and was not aware that if you want to leave the size of the vector open ended, all you had to do is remove the parenthesis.

    You are right to believe that the vector is initially empty and that I want to create a vector of constructors for the class Pupils. How would I modify the line so that this is what happens? I have tried:

    pupilnames.push_back (name);

    but recieve the error message:

    task4driver.cc: In function `int main(int, char**)':
    task4driver.cc:57: no matching function for call to `std::vector<Pupil,
    std::allocator<Pupil> >::push_back(std::string&)'
    /usr/local/include/c++/3.1.1/bits/stl_vector.h:490: candidates are: void
    std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = Pupil, _Alloc
    = std::allocator<Pupil>]

    Any ideas?
    Last edited by markb_1984; April 14th, 2003 at 02:48 PM.
  12. #7
  13. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,145
    Rep Power
    2222
    Judging from the prototype in stl_vector.h (which is included by vector.h), pupilnames.push_back is looking for a reference to an object of class Pupil, so of course it's going to complain when you try to feed it a string instead.

    You will need to instantiate a Pupil, call its SetName method, then push it into pupilnames, something like:
    Code:
    {
        Pupil pupil();
        pupil.SetName(name);
        pupilnames.push_back(pupil);
    }
    Please note that pupil's scope is limited to the code block it's declared in and that it will be destroyed as soon as you leave the code block. I am assuming that a vector will make its own copy of whatever is passed to it and that the original object can safely be destroyed.

    Or if it's more your style, declare a pointer to Pupil, construct an object with new, call SetName, dereference the pointer in the call to push_back, and delete the object:
    Code:
        Pupil *pupil;
        pupil = new Pupil();
        pupil->SetName(name);
        pupilnames.push_back(*pupil);
        delete pupil;
  14. #8
  15. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2003
    Posts
    154
    Rep Power
    14
    My input file is as follows:

    Kevin 20 42
    Lee 60 58

    The lines which I am using to read in the data of this file and then output it on screen making use of the pupil class are:

    vector <Pupil> pupilnames;

    string name;

    int i=0, m1w, m1m;

    while (inFile)
    {

    if (!inFile.fail())
    {

    inFile >> name, m1w, m1m;
    Pupil *pupil;
    pupil = new Pupil();
    pupil->setName(name);
    pupilnames.push_back (*pupil);
    delete pupil;
    pupilnames[i].setmodule1Weight(m1w);
    pupilnames[i].setmodule1Mark(m1m);

    i++;
    }
    }

    for (int i = 0; i < 2; i++)
    {

    cout << pupilnames[i].getName() << endl
    << pupilnames[i].getmodule1Weight() << endl
    << pupilnames[i].getmodule1Mark() << endl;
    }

    Allthough this code compiles and the program executes ok, the problem is that unexpected results are produced.

    What I wanted to happen was to create a loop which would go to the first line of the file and read in the name (Kevin), m1w (20), m1m (42). Then using the vector, a constructor would then be created assigning the variable name (Kevin) as the name of the constructor. Then using the mutator/set methods of the class, the variables m1w and m1m should then be stored in the object 'Kevin'. I then intended that the loop would proceed in doing the same on all subsequent lines of the file until no more lines were left (!inFile.eof()). Instead when I run this program, I get the following output:

    Kevin
    134514273
    1073766787
    20
    134514273
    1073766787
    42
    134514273
    1073766787

    This to me looks like instead of each iteration of the loop going to the next line and reading in the appropriate data and assigning them to the variables, what I think is happening is that on each oteration, the loop goes to the next word of the file and then assigns it to the name variable, but since the loop only looks at one word at a time, the other two variables don't get assigned to anything therefore producing garbage values upon output.

    Seems to me to me that the problem is therefore related to the while loop although could easily be something else causing the problem.

    Thoughts kindly appreciated.
  16. #9
  17. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2003
    Posts
    154
    Rep Power
    14
    Solved it! The problem was the line:

    inFile >> name, m1w, m1m;

    Should have read:

    inFile >> name >> m1w >> m1m;

    Since writing this post, I've encountered another problem of which I would very much appreciate your advice.

    I've now got a vector of constructors with loops to store in the attributes of each object.

    I would now like to sort the vector using bubble sort so that the first pupil in the vector corresponds to the pupil obtaining the highest overall mark.

    This is the code I'm using:

    for (int i = 0; i < (pupilnames.size () - 1); i++)
    {

    for (int j = 0; j < (pupilnames.size () - 1); j++)
    {

    if (pupilnames[j].getfinalMark () > pupilnames[j + 1].getfinalMark ())
    {

    string temp = pupilnames[j].getName();
    pupilnames[j] = pupilnames[j + 1]; // Line 90
    pupilnames[j + 1] = temp; // Line 91
    }
    }
    }

    When compiling, I get the following error message:

    task4dr.cc: In function `int main(int, char**)':
    task4dr.cc:91: no match for `Pupil& = std::string&' operator
    task4dr.cc:90: candidates are: Pupil& Pupil::operator=(const Pupil&)

    The error message indicates lines 90 and 91 to be the problem, and these have been commented show you can see which lines they refer to.

    Thanks in advance.
    Last edited by markb_1984; April 15th, 2003 at 05:58 AM.
  18. #10
  19. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,145
    Rep Power
    2222
    Originally posted by markb_1984

    ...

    Pupil *pupil;
    pupil = new Pupil();
    pupil->setName(name);
    pupilnames.push_back (*pupil);
    delete pupil;
    pupilnames[i].setmodule1Weight(m1w);
    pupilnames[i].setmodule1Mark(m1m);
    You will want to keep your style consistent. You should call all three methods the same way. Either call all three methods as you call setName and then push pupil into the vector, or push pupil into the vector and then call all the methods as you call setmodule1Weight.

    Also, be sure that you understand what each line of code is doing well enough to be able to explain it. A good example is for you to explain why you are passing *pupil to push_back.
  20. #11
  21. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,145
    Rep Power
    2222
    Originally posted by markb_1984
    string temp = pupilnames[j].getName();
    pupilnames[j] = pupilnames[j + 1]; // Line 90
    pupilnames[j + 1] = temp; // Line 91
    }
    }
    }

    When compiling, I get the following error message:

    task4dr.cc: In function `int main(int, char**)':
    task4dr.cc:91: no match for `Pupil& = std::string&' operator
    task4dr.cc:90: candidates are: Pupil& Pupil::operator=(const Pupil&)
    Think about what you are doing. You want to have two Pupil objects swap places in the vector. What your code appears to be trying to do is to swap the names of the Pupil objects without moving any of the rest of the data.

    Make temp a Pupil object and assign pupilnames[j] to it.

    BTW, the compile error was because you were trying to assign a string to a Pupil. If you really wanted to change that Pupil's name, you should have used the setName method.

    It's been a while since I've done the bubble sort, but your use of the indices don't look right to me. You need to play computer here -- test out your code by executing it yourself with pencil and paper. Create a short list on paper and run through it through your bubble sort by hand.

IMN logo majestic logo threadwatch logo seochat tools logo