How do I use classes to store and print out student objects

closed account (zhfjE3v7)
Hi, I'm relatively new to C++ and I am trying to dynamically store student objects using classes, but I am getting strange errors when I try to compile it. Here is what I have so far.

student.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include "Name.h"
#include "Student.h"
#include<iostream>
#include<string>
#include<set>
using namespace std;

int main()
{
	Student s1();
	set<Student *> s;
	while(cin>>s1)
	{
		s.insert(new Student(s1));
	}
	s1.display(cout);
}


Name.h - handles the name of the student
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#ifndef NAME_H
#define NAME_H
#include <string>
#include <iostream>
class Name{
    public:
        explicit Name(const std::string& first = "",const std:: string& last = ""):first_(first),last_(last){}
        friend std::ostream& operator<<(std::ostream&, const Name&);
        friend std::istream& operator>>(std::istream&, Name&);
	private:
        std::string first_;
        std::string last_;
};

inline std::ostream& operator<<(std::ostream& os, const Name& n){
    return os << n.first_<< " " << n.last_;
}
inline std::istream& operator>>(std::istream& is, Name& n){
    std::string first,last;
    if(is >> first >> last ){
        n.first_ = first;
        n.last_ = last;
    }
    else
        is.setstate(std::ios_base::failbit);
    return is;
}
#endif 


Student.h - stores a student along with their grades for all their classes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#ifndef STUDENT_H
#define STUDENT_H
#include<string>
#include<iostream>
#include<map>
#include "Name.h"
typedef std::map<std::string, int> GradeMap;

class Student {
public:
	Student(const std::string id="", const Name& name = Name(), GradeMap grades = GradeMap());
	Student(const Student& s):id_(s.id_), name_(s.name_){}
	virtual ~Student(){}
	friend std::istream& operator>>(std::istream& is, Student& s);
	
	virtual void display(std::ostream& os) const{
		os << "ID: " << id_ << "Name: " << name_ << std::endl;
		
		for(std::map<std::string, int>::const_iterator it = grades_.begin(); it != grades_.end(); ++it)
			os<<it->first<<' '<<it->second;
	}
	
private:
	std::string id_;
	Name name_;
	GradeMap grades_;

};

inline std::istream& operator>>(std::istream& is, Student& s)
{
	std::string id;
	std::string key;
	int grade;
	int count = 0;
	Name name;
	
	if(is>>id>>name>>count){
		s.id_ = id;
		s.name_ = name;
	}
	
	for(int i = 0; i < count; i++)
	{
		if(is>>key>>grade)
		{
			s.grades_[key] = grade;
		}
	}
}
#endif 


Here is the text file I am testing my program with using I/O redirection. The first row is the id of the student followed by their name and the number of courses they have taken.

1
2
3
4
5
6
7
8
9
10
11
111111111
john doe
3
comp2510 25
phys2525 60
chem3512 45
222222222
jane smith
2
bio1510 90
eng2514 85


Here is the error that I am getting.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
student.cpp: In function 'int main()':
student.cpp:12:13: error: ambiguous overload for 'operator>>' in 'std::cin >> s1
'
/usr/lib/gcc/i686-pc-cygwin/4.5.3/include/c++/istream:120:7: note: candidates ar
e: std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_Char
T, _Traits>::operator>>(std::basic_istream<_CharT, _Traits>::__istream_type& (*)
(std::basic_istream<_CharT, _Traits>::__istream_type&)) [with _CharT = char, _Tr
aits = std::char_traits<char>, std::basic_istream<_CharT, _Traits>::__istream_ty
pe = std::basic_istream<char>] <near match>
/usr/lib/gcc/i686-pc-cygwin/4.5.3/include/c++/istream:124:7: note:
   std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_Char
T, _Traits>::operator>>(std::basic_istream<_CharT, _Traits>::__ios_type& (*)(std
::basic_istream<_CharT, _Traits>::__ios_type&)) [with _CharT = char, _Traits = s
td::char_traits<char>, std::basic_istream<_CharT, _Traits>::__istream_type = std
::basic_istream<char>, std::basic_istream<_CharT, _Traits>::__ios_type = std::ba
sic_ios<char>] <near match>
/usr/lib/gcc/i686-pc-cygwin/4.5.3/include/c++/istream:131:7: note:
   std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_Char
T, _Traits>::operator>>(std::ios_base& (*)(std::ios_base&)) [with _CharT = char,
 _Traits = std::char_traits<char>, std::basic_istream<_CharT, _Traits>::__istrea
m_type = std::basic_istream<char>] <near match>
student.cpp:14:26: error: no matching function for call to 'Student::Student(Stu
dent (&)())'
Student.h:12:2: note: candidates are: Student::Student(const Student&)
Student.h:11:2: note:                 Student::Student(std::string, const Name&,
 GradeMap)
student.cpp:16:5: error: request for member 'display' in 's1', which is of non-c
lass type 'Student()'

any help would be appreciated.
Last edited on
closed account (zhfjE3v7)
bump
Could you post the first 20 or so lines of student.cpp?
That's where the errors seem to be coming from...
closed account (zhfjE3v7)
What i posted here is all i have....
closed account (zhfjE3v7)
bump
closed account (zb0S216C)
1) In Name.h, the use of explicit will be ignored by the compiler. Consider reading up on that.
2) In Student.h, Student::display doesn't need to be virtual.
3) In Student.h, instead of overloading the operator as a friend, why not overload it internally?

Can you post the contents of Student.cpp? It seems some of the errors are originating from there.

Wazzak
closed account (zhfjE3v7)
Oh sorry I mistyped my first post its suppose to be student.cpp

also is there a difference if i overload operator internally? Because i thought it would be less clutter in the class.
Last edited on
closed account (zb0S216C)
In Student.cpp, on line 10, s1 is not an object declaration but a function prototype. It returns a Student object, and takes no arguments. Remove the parentheses. C++ allows function prototypes within local scopes, which is why you never get an error from such a declaration.

Still in Student.cpp, there's a memory leak - multiple, actually. Every call to new/new[] must have a corresponding call to delete/delete[]. As I've stated in another thread, C++ doesn't have a garbage collection system, so the programmer is in charge of how the memory is used and when it's released.

ogglock wrote:
also is there a difference if i overload operator internally?

An internally overloaded operator has precedence over externally overloaded operators (assuming that the operators operate on the object in question). Personally, I prefer to overload an operator internally - it's more explicit.

Wazzak
Last edited on
closed account (zhfjE3v7)
Thanks for responding so fast. I tried out what you said, but it still can't compile

here is the student.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include "Name.h"
#include "Student.h"
#include<iostream>
#include<string>
#include<set>
using namespace std;

int main()
{
	Student s1;
	set<Student *> s;
	while(cin>>s1)
	{
		s.insert(new Student(s1));
	}
	s1.display(cout);
	
	for(set<Student *>::iterator it = s.begin(); it != s.end();++it)
		s.clear();
}


and the error I'm getting is

1
2
3
4
5
6
7
8
/cygdrive/c/Users/Michael/AppData/Local/Temp/cc7cD3Z4.o:student.cpp:(.text+0xf7)
: undefined reference to `Student::Student(std::basic_string<char, std::char_tra
its<char>, std::allocator<char> >, Name const&, std::map<std::basic_string<char,
 std::char_traits<char>, std::allocator<char> >, int, std::less<std::basic_strin
g<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pa
ir<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const,
 int> > >)'
collect2: ld returned 1 exit status 


I'm starting to think that the problem is in my student.h file because of the map that I am implementing there.
closed account (zb0S216C)
Where's the definition for:
Student(const std::string id="", const Name& name = Name(), GradeMap grades = GradeMap())? I can't see it.

Wazzak
Last edited on
closed account (zhfjE3v7)
you mean something like

 
Student(const std::string id="", const Name& name = Name(),const GradeMap & grades = GradeMap()):id_(id),name_(name),grades_(grades){}


?

but does that mean I don't need the

 
Student(const Student& s):id_(s.id_), name_(s.name_){}


constructor anymore?

EDIT:

okay ignore what I said above I managed to find the root cause of my problem. It is the line

1
2
3
4
while(cin>>s1)
{
      //do whatever
}


which is weird because it works fine if i do

 
cin>>s1;
Last edited on
Topic archived. No new replies allowed.