Using Scope operator and finding meaning in errors

Pages: 12
Ok so my question is when dividing up a program into header files and source files, as our teacher refers to as "Modules" I am running into a little confusion on exactly what goes where.
I know the function prototypes go in the header files, and that the meat of the code is implemented into the source files. But do those also include the function prototypes? This seems to kinda defeat the purpose but it obviously does it for the reason to not have to compile everything all over again.

My bigger question is that I am getting about 8 errors that are trivial but I cannot figure out why. I know that the code is probably in the wrong area or I am not putting it correctly in the separate files.

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
//Here is my student.cpp file
  #include "student.h"

using namespace std;
Student::Student
{
}
struct Student () {
	string name;
	int credits;
	double qualityPoints;
};

void addGrade(Student& aStudent, string grade, int credits)
{
	aStudent.credits += credits;
	double v = findGradeValue(gradeValues, 11, grade);
	aStudent.qualityPoints += credits * v;
}

double Student::computeGPA (const Student& aStudent)
{
	if (aStudent.credits > 0)
		return aStudent.qualityPoints / aStudent.credits;
	else
		return 0.0;
}

//And here is my student.h file
#ifndef STUDENT_H_INCLUDED
#define STUDENT_H_INCLUDED
#include <fstream>

#include <string>
using namespace std;

class student
{
    public:

    void addGrade(Student& aStudent, std::string grade, int credits);
    double computeGPA (const Student& aStudent);

};



#endif // STUDENT_H_INCLUDED 


Most of the errors are forward declarations, and that they are not defined. Not that they are not defined in the scope, just not defined.
student.h|12|error: 'Student' has not been declared|
student.h|13|error: 'Student' does not name a type|
student.h|13|error: ISO C++ forbids declaration of 'aStudent' with no type [-fpermissive]|
student.cpp|4|error: 'Student' does not name a type|
student.cpp|7|error: expected unqualified-id before ')' token|
student.cpp||In function 'void addGrade(Student&, std::string, int)':|
student.cpp|15|error: invalid use of incomplete type 'struct Student'|
student.cpp|7|error: forward declaration of 'struct Student'|
student.cpp|16|error: 'gradeValues' was not declared in this scope|
student.cpp|16|error: 'findGradeValue' was not declared in this scope|
student.cpp|17|error: invalid use of incomplete type 'struct Student'|
student.cpp|7|error: forward declaration of 'struct Student'|
student.cpp|20|error: invalid use of incomplete type 'struct Student'|
student.cpp|7|error: forward declaration of 'struct Student'|

I know a few fixes would make all the errors go away. But my limited knowledge keeps me from understanding what it is I am doing wrong. Any insight on my problems would be much appreciated.
First of all, you have a class student and a struct Student.

Note the lower case and uppercase respectively. C++ is case sensitive.

In the .cpp file, you provide a function body for a Student constructor, but the Student struct hasn't been declared yet - you only declare it right after.

What exactly is the point of having a class and a struct - which could basically be the same thing. Why don't you merge them?
Last edited on
The requirements are very specific. And I can get this right doing it a different way. But its the way that it is graded and I am failing to compile. I now have it so that it compiles correctly, but not to the point where it works the "way it's supposed to". It's very ridiculous but it is what it is. But to answer your question I do think I merged them last night. I couldn't look at it any longer.
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
//Here is my new header file

#ifndef STUDENT_H_INCLUDED
#define STUDENT_H_INCLUDED
#include <fstream>

#include <string>
using namespace std;

class Student
{
    public:
    Student(std::string name, int credits, double qp);

    void addGrade(Student& aStudent, std::string grade, int credits);
    double computeGPA (const Student& aStudent);

    string name;
	int credits;
	double qualityPoints;

};



#endif // STUDENT_H_INCLUDED

//And here is my new source code for it.

#include "student.h"
#include "gradeValue.h"

using namespace std;
Student::Student(std::string Name, int Credits, double Qp)
{
    name = Name;
    credits = Credits;
    qualityPoints = Qp;
}

void Student::addGrade(Student& aStudent, string grade, int credits)
{
	aStudent.credits += credits;
	double v = findGradeValue(grade);
	aStudent.qualityPoints += credits * v;
}

double Student::computeGPA (const Student& aStudent)
{
	if (aStudent.credits > 0)
		return aStudent.qualityPoints / aStudent.credits;
	else
		return 0.0;
}

//And here is another source file, this is part of a bigger program and this was
// not meant to be edited in any way, but to get it to work I added a few things.

#include <fstream>
#include <iostream>
#include <iomanip>
#include <string>
#include "student.h"
#include "gradeValue.h"

using namespace std;

void gpaCalc (istream& input, ostream& output)
{
  string name;
  getline (input, name);
  int credits;
  double qp;
  input >> credits >> qp;
  Student student(name, credits, qp);
  string grade;
  input >> grade >> credits;
  while (grade != "0" && credits != 0)
   {
	   student.addGrade (student, grade, credits);//Here I also added student
	   input >> grade >> credits;           //It's supposed to work without them
   }
   double gpa = student.computeGPA(student);//Here I added student
   output << student.name << ' '
	  << fixed << setprecision(2) << gpa << endl;
}


int main (int argc, char** argv)
{
  if (argc > 1)
    {
      ifstream inputFile (argv[1]);
      gpaCalc (inputFile, cout);
    }
  else
    gpaCalc (cin, cout);
  return 0;
}

My main problem is the only error that I get now, is a Win@16 error.
I have never encountered that before. If I add student to the member function, it works fine, but when I remove them it never compiles. I'm stumped.
gpaCalc.cpp|33|error: no matching function for call to 'Student::computeGPA()'|

This is the error I get when I make the gpaCalc.ccp the way it is supposed to be, now I do not get the Win@16 error. Kinda stumped as the error that I am getting is in a file I am not supposed to edit.
Maybe you could post your exact assignment requirements? I'd be glad to walk your through them.
**Your task for this assignment is to add a student module in student.h and student.cpp. This should
-Provide your Student struct
-Add a constructor to initialize the student data.
-Convert the addGrade and computeGPA functions from the prior assignment into member functions of the Student struct.
--You may not change any of the provided code for the program outside of student.h and student.cpp. Your new code must be consistent with the calls already written into the other code.

And thanks guys for the answers. I'm just irritated that it has to be a "specific" way.
Make sure your testcase is self-contained and actually reproduces the problem

A testcase is said to reproduce the problem if, when we independently try to compile and run the testcase locally, we get the same compiler error (or our compiler's version of it) or erroneous program output specified in the testcase (see point 3). A testcase that does not reproduce the problem is useless: if we get different errors or output, then the code apparently does not correspond to the actual code you're having problems with, and consequently analyzing it is pointless. The same is true if the testcase works fine.

¿what's gradeValue.h ?

> Convert the addGrade and computeGPA functions from the prior assignment
> into member functions of the Student struct.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//declaration
//double computeGPA (const Student& aStudent); //this was a global function
double computeGPA () const; //as a member function

//definition
double Student::computeGPA () const
{
	if (this->credits > 0)
		return this->qualityPoints / this->credits;
	else
		return 0.0;
}

//use
student.computeGPA();
(double post)
Last edited on
I'm sorry about the test cases. I also have two more files, gradeValue.h and .ccp respectively that also where not meant to be edited.
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
//Here is the gradeValue.h

#ifndef GRADEVALUE_H
#define GRADEVALUE_H

#include <string>

double findGradeValue (std::string grade);



#endif

//And its respective .cpp source file

#include "gradeValue.h"
#include "student.h"

using namespace std;

struct GradeValue {
	string  grade;
	double value;
};


const GradeValue gradeValues[] = {
		{"A", 4.0},
		{"A-", 3.7},
		{"B+", 3.3},
		{"B",  3.0},
		{"B-", 2.7},
		{"C+", 2.3},
		{"C",  2.0},
		{"C-", 1.7},
		{"D+", 1.3},
		{"D",  1.0},
		{"F",  0.0}
};

const int numGradeValues = 11;

double findGradeValue (string grade)
{
  for (int i = 0; i < numGradeValues; ++i)
    if (gradeValues[i].grade == grade)
      return gradeValues[i].value;
  return gradeValues[numGradeValues-1].value;

}


And in this while in the student.cpp file I would need to add something like an altered prototype above the definition? Because when I added them to the .h file thats what I thought I was doing for the member function.
When converting to member functions of the student struct, wouldn't that have to be done inside the header file in which I made the struct? And that would mean that I don't have to actually modify the .cpp functions and definitions right?
I have no issue building


> And in this while in the student.cpp file I would need to add something like an altered prototype above the definition? Because when I added them to the .h file thats what I thought I was doing for the member function.

I don't understand what you mean. Maybe I was not clear
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Student
{
    public:
    Student(std::string name, int credits, double qp);

    //see computeGPA() explanation
    //void addGrade(Student& aStudent, std::string grade, int credits);
    void addGrade(std::string grade, int credits);

    //this declaration would make the caller object useless
    //by instance, student.computeGPA(student) would be equivalent to another.computeGPA(student)
    //double computeGPA (const Student& aStudent);
    //so instead use this other declaration, and modify the definition in correspondence.
    double computeGPA () const;

    string name;
	int credits;
	double qualityPoints;

};
Last edited on
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
//So here is what I got from ne555
//Modified prototype inside of the student.h file

#ifndef STUDENT_H_INCLUDED
#define STUDENT_H_INCLUDED
#include <fstream>

#include <string>
using namespace std;

class Student
{
    public:
    Student(std::string name, int credits, double qp);

    void addGrade() std::string, int; ///Student& aStudent, std::string grade, int credits removed from ()'s
    double computeGPA () const ;///const Student& aStudent removed from ()'s

    string name;
	int credits;
	double qualityPoints;

};



#endif // STUDENT_H_INCLUDED 

And this way I get a whole host of errors. This is incorrect or would I also have to do this for the source file for student? I will check that right now.
look carefully at line 16
it should be void addGrade( std::string, int );

> would I also have to do this for the source file for student?
of course, prototypes must match.

the use would be modified too.
Instead of student.addGrade (student, grade, credits); would be student.addGrade (grade, credits);
and student.computeGPA(student) becomes student.computeGPA()
(note how there is no repetition)
Last edited on
ne555 you've been way more help than my professor could even imagine being.
Now I have 3 more errors that have to do with the function definition in void addGrade:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void addGrade( std::string, int );
{
	aStudent.credits += credits;
	double v = findGradeValue(grade);
	aStudent.qualityPoints += credits * v;
}

 double computeGPA () const ;
{
	if (aStudent.credits > 0)
		return aStudent.qualityPoints / aStudent.credits;
	else
		return 0.0;
}

student.cpp|2|error: expected unqualified-id before '{' token|
student.cpp|8|error: non-member function 'double computeGPA()' cannot have cv-qualifier|
student.cpp|9|error: expected unqualified-id before '{' token|
||=== Build failed: 3 error(s), 0 warning(s) (0 minute(s), 1 second(s)) ===|

I'm sorry i did not read the build right.

And in the calcGPA.cpp I have long since removed the student in the functions as that was part of the other way for me to work around the code.
Last edited on
Now if I delete:
1
2
3
4
5
6
7
const
//after 
double computeGPA () const;
//so it is now
double computeGPA ();
//and now error "cannot have cv-qualifier" is gone
//Just left with the unqualified-id before '{' token 
Two things:

1.) Why do you have semi-colons between the parentheses and the opening braces?

2.) If those functions belong to the student class (which they do), then you need to prefix them with the proper scope resolution.

1
2
3
4
5
6
7
void Student::addGrade(std::string, int) {
	/*code*/
}

double Student::computeGPA() const {
	/*code*/
}
Last edited on
@ xismn

Even if I remove the semi colon and input the scope resolution operator for struct student, in reference to addGrade and computeGPA I get "aStudent and grade are not declared in this scope" error inside the student.cpp file.
When you do foo.bar(); you are sending the `bar()' message to the `foo' object.
in order to operate with the caller, it is passed as a parameter in the form of the this pointer.

1
2
3
4
5
6
void addGrade( std::string grade, int credits ) //if you don't give them a name, ¿how do you expect to use them?
{
	this->credits += credits;
	double v = findGradeValue(grade);
	this->qualityPoints += credits * v;
}
@ne555

I understand this mistake now, but even with these added I still get the same error.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//Prototypes in the header file.
 void addGrade( std::string grade, int credits );//Added grade and credits
 double computeGPA () const ;//Not sure if I should add anything to this one
//The only things I have left out are "Student& aStudent" which were previously
//part of the two functions.

void Student::addGrade( std::string grade, int credits )//Added grade and credits
{
    aStudent->credits += credits;//The pointer (->) and the dot operator are interchangeable?
	double v = findGradeValue(grade);
	aStudent->qualityPoints += credits * v;
}

double Student::computeGPA()const//Again not sure if anything is to be added
{
	if (aStudent->credits > 0)
		return aStudent.qualityPoints / aStudent.credits;
	else
		return 0.0;
}
¿don't you see that this is highlighted?
Pages: 12