Re: Classes and Constructors
year is an enum and not an int. As per the notes, the enum definition needs to go before the class definition.
You don't usually put using namespace in a header file as this isn't considered good practice (the reason will come later when you cover namespaces in more detail).
The getters should be declared a const - not the setters! setters change the class member variables so can't be const whereas the getters don't change anything and so can (should be) const.
Quote:
I can't seem to understand the rest
For student.cpp, what are not understanding - the assignment is fairly clear as to what is needed?
Also for hw3.cpp, the assignment details what is required, so what problems are you having?
Re: Classes and Constructors
Quote:
Originally Posted by
Semirxbih
Let me know if I'm on the right track or give me any help/tips I can use,
A common newbie mistake is to write lots and lots of code without testing anything.
Instead first write the smallest possible version of the exercise that does at least something and make sure it runs correctly. Then add code in small steps and after each addition you test and make sure it works. In no time you will have a running version of the whole exercise ready to hand in.
Re: Classes and Constructors
This is what I have so far, I still need some help.
Student.h file:
Code:
#ifndef STUDENT_H
#define STUDENT_H
#include <iostream>
#include <string>
#include <cstdlib>
struct Name {
std::string firstName;
std::string lastName;
};
enum Year {
FRESHMAN = 1,
SOPHMORE,
JUNIOR,
SENIOR,
};
class Student
{
private:
Name name;
int idNumber;
std::string department;
Year year;
public:
Student(const std::string& student, int id_number, const std::string& department, Years);
Student(const std::string& student, int id_number);
Student();
int getidNumber();
std::string getName();
std::string getdepartment();
Year getYear();
void setName(const Name& student_name);
void setidNumber(int id_number);
void setdepartment(const std::string student_department);
void setyear(Year students_current_year);
};
#endif
Here is the error that Student.cpp is giving me:
Code:
Student.cpp:8:1: error: 'Student' does not name a type
Student::Student(const std::string& student, int id_number, const std::string& department, Year year)
^~~~~~~
Student.cpp:16:1: error: 'Student' does not name a type
Student::Student(const std::string& student, int id_number)
^~~~~~~
Student.cpp file:
Code:
#ifndef STUDENT_H
#define STUDENT_H
#include <string>
#include <cstdlib>
#include "Student.h"
Student::Student(const std::string& student, int id_number, const std::string& department, Year year)
{
Name name = setName();
idNumber = setidnumber();
department = setdepartment();
Year year = setyear();
};
Student::Student(const std::string& student, int id_number)
{
Name name = std::student;
idNumber = std::id_number;
};
#endif
hw3.cpp file:
Code:
#ifndef STUDENT_H
#define STUDENT_H
#include <iostream>
#include <string>
#include <cstdlib>
#include "Student.h"
#include "Student.cpp"
using namespace std;
int main()
{
Student::student()
void displayStudent(Student);
return 0;
}
#endif
Let me know where I'm making mistakes/lead/help me towards the right direction. Thanks so much!
Re: Classes and Constructors
So I've removed the #include guards from the cpp files but here is the list of compiler errors now:
Code:
Student.cpp: In constructor 'Student::Student(const string&, int, const string&, Year)':
Student.cpp:7:15: error: expected primary-expression before 'const'
Name name = const setName;
^~~~~
Student.cpp:8:26: error: 'setidnumber' was not declared in this scope
idNumber = setidnumber();
^
Student.cpp:9:30: error: no matching function for call to 'Student::setdepartment()'
department = setdepartment();
^
In file included from Student.cpp:3:0:
Student.h:39:14: note: candidate: void Student::setdepartment(std::__cxx11::string)
void setdepartment(const std::string student_department);
^~~~~~~~~~~~~
Student.h:39:14: note: candidate expects 1 argument, 0 provided
Student.cpp:10:8: error: declaration of 'Year year' shadows a parameter
Year year = setyear();
^~~~
Student.cpp:10:23: error: no matching function for call to 'Student::setyear()'
Year year = setyear();
^
In file included from Student.cpp:3:0:
Student.h:40:14: note: candidate: void Student::setyear(Year)
void setyear(Year students_current_year);
^~~~~~~
Student.h:40:14: note: candidate expects 1 argument, 0 provided
Student.cpp: In constructor 'Student::Student(const string&, int)':
Student.cpp:15:15: error: conversion from 'const string {aka const std::__cxx11::basic_string<char>}' to non-scalar type 'Name' requested
Name name = student;
^~~~~~~
Re: Classes and Constructors
Quote:
Originally Posted by
wolle
A common newbie mistake is to write lots and lots of code without testing anything.
Instead first write the smallest possible version of the exercise that does at least something and make sure it runs correctly. Then add code in small steps and after each addition you test and make sure it works. In no time you will have a running version of the whole exercise ready to hand in.
I agree re testing and step-wise enhancement. However, first you design the program, then code against the design. IMO the worst thing that programmers can do (especially newbies) is to start coding without first producing a co-coherent design. This includes such things as output requirements, input requirements, algorithms, data structures, class design etc etc.
Re: Classes and Constructors
Code:
void displayStudent(Student);
That is a function declaration in main()?? :confused:
The class getters should be const.
This is trying to define some sort of class constructor?? but is invalid. I think you're trying to define a variable student of type Student? Consider
Code:
Student::Student(const std::string& student, int id_number)
{
Name name = std::student;
idNumber = std::id_number;
};
student and id_number are not members of the std namespace. They are member variables of the class. Consider
Code:
Student::Student(const std::string& stud, int id_number) : student(stud), idNumber(id_number) {}
Code:
Student::Student(const std::string& student, int id_number, const std::string& department, Year year)
{
Name name = setName();
idNumber = setidnumber();
department = setdepartment();
Year year = setyear();
};
This is not how you initialise member variables in a constructor. This is trying to define and initialise variables in the function which are only valid until the end of the function. Also the setters take an argument and return void so can't be used as part of an assignment. Consider
Code:
Student::Student(const std::string& student, int id_number, const std::string& department, Year year) : student(student), idNumber(id_number), department(department), year(year) {}
Note that no terminating ; is needed as this is a function, not a struct/class definition.
Also note that it isn't considered good practice to have a function parameter with the same name as a member variable.
Re: Classes and Constructors
I've tried your way, and I'm still getting errors :(
Here is the updated code:
Code:
#ifndef STUDENT_H
#define STUDENT_H
#include <iostream>
#include <string>
#include <cstdlib>
struct Name {
std::string firstName;
std::string lastName;
};
enum Year {
FRESHMAN = 1,
SOPHMORE,
JUNIOR,
SENIOR,
};
class Student
{
private:
Name name;
int idNumber;
std::string department;
Year year;
public:
void setName(Name student_name);
std::string getName() const;
void setidNumber(int id_number);
int getidNumber() const;
void setdepartment(std::string student_department);
std::string getdepartment() const;
void setYear(Year students_current_year);
Year getYear() const;
};
#endif
Student.cpp
Code:
#include <string>
#include <cstdlib>
#include "Student.h"
using namespace std;
Student::Student(Student& Name student_name, int id_number, std::string student_department, Year students_current_year)
{
name = student_name;
idNumber = id_number;
department = student_department;
year = students_current_year;
}
// Student::Student();
// Student::Student();
Re: Classes and Constructors
Code:
Student::Student(Student& Name student_name, int id_number, std::string student_department, Year students_current_year)
You haven't specified a class constructor in the class definition. It was included in post #4 but not in post #8.
Re: Classes and Constructors
Quote:
Originally Posted by
2kaud
I agree re testing and step-wise enhancement. However, first you design the program, then code against the design. IMO the worst thing that programmers can do (especially newbies) is to start coding without first producing a co-coherent design. This includes such things as output requirements, input requirements, algorithms, data structures, class design etc etc.
Certainly, but I thought the room for design in this case was very limited since the topic is an exercise specified in great detail.
The program design method I have in mind is called Stepwise Refinement which was introduced by N. Wirth, the inventor of Pascal. It may not suit everyone but at least it's a method and that's better than cluelessly muddle along. As important as it is to learn the intricacies of specific languages is it to learn how to develop programs. It seems forgotten in education today. At least I get that impression.
The OP has made a false start. To recover s/he should reduce program complexity by removing code until there is a working solution and then add code in small working steps until the desired result is at hand.
Re: Classes and Constructors
Still need some help with this.
Re: Classes and Constructors
Quote:
Originally Posted by
Semirxbih
Still need some help with this.
You asked for advice and you got it but you are not following it.
Reduce the code until it works. Start with just this,
Code:
class Student {
public:
Student() { // default constructor
std::cout << "The student default constructor was called" << std::endl;
}
};
I don't know what your test system looks like but now when you do any of these,
Code:
Student student1; // instantiates a Student object calling its default constructor
Student student2 = Student(); // the same
auto student3 = Student(); // the same (and recommended by some top gurus since C++ 11)
the message in Student's default constructor should be printed. When it does, add something small to Student and make sure it works as expected before continuing with the next small step, etcetera. This is how real programmers work. The difference between a newbie and a pro is just how big a small step is :).
I note you're supposed to split the definition of Student into a .h and a .cpp file. I don't know why this silly convention is upheld in newbie courses today but I guess you better do as you're told. But know that this is not necessary, even unnecessary with today's extremely capable compilers.
Re: Classes and Constructors
Quote:
Originally Posted by
Semirxbih
Still need some help with this.
Ok. Here's your starter for 10. This will create and display the class instances for the required constructors.
Code:
#include <iostream>
#include <string>
struct Name {
std::string firstName;
std::string lastName;
};
enum Year {
FRESHMAN = 1,
SOPHMORE,
JUNIOR,
SENIOR,
};
class Student
{
public:
Student(const Name& student, int id_number, const std::string& depart, Year yr) :
name(student), idNumber(id_number), department(depart), year(yr) {}
Student(const Name& student, int id_number) : name(student), idNumber(id_number) {}
Student() {}
void displayStudent()
{
std::cout << "Name: " << name.firstName << " " << name.lastName << std::endl;
std::cout << "id: " << idNumber << std::endl;
std::cout << "department: " << department << std::endl;
std::cout << "Year: " << (int)year << std::endl << std::endl;
}
private:
Name name;
int idNumber = 0;
std::string department;
Year year = FRESHMAN;
};
int main()
{
Student s1 { { "f1", "l1" }, 1, "d1", SENIOR };
Student s2 { {"f2", "l2"}, 2, "d2", JUNIOR };
Student s3;
s1.displayStudent();
s2.displayStudent();
s3.displayStudent();
}
I'll leave it as an exercise if you want it split into a .h and .cpp files.
You now need to add the getters and setters and use them as appropriate.
Re: Classes and Constructors
Quote:
I note you're supposed to split the definition of Student into a .h and a .cpp file. I don't know why this silly convention is upheld in newbie courses today but I guess you better do as you're told. But know that this is not necessary, even unnecessary with today's extremely capable compilers.
Whilst knowledge of separate compilation units and include-guards is important, IMO it's not something that should be introduced early into a newbie c++ course. There's plenty of other good c++ stuff that I'd teach ahead of this.
Re: Classes and Constructors
Quote:
Originally Posted by
Semirxbih
Still need some help with this.
How are you learning c++? What book(s), if any, are you using?
Have at look at this thread http://forums.codeguru.com/showthrea...-books-about-C and in particular post #10.
Re: Classes and Constructors
Quote:
Originally Posted by
2kaud
Whilst knowledge of separate compilation units and include-guards is important, IMO it's not something that should be introduced early into a newbie c++ course. There's plenty of other good c++ stuff that I'd teach ahead of this.
Include guards will always be necessary because otherwise a violation of the One Definition Rule (ODR) will occur sooner or later for sure.
The ODR is defined by the C++ language but the splitting of source code into .h and .cpp files is not. It's a convention and I don't understand why it's routinely taught to C++ newbies today. Newbies get the impression that such splitting is an important part of C++. You often see in forums like this how they proudly present meticulously split code when the only thing it accomplishes is making the code more complicated to follow.
At least up to medium sized programs (say 1000 .h files which far exceeds a typical homework or student project) using just one translation unit is perfectly fine. I've experimented with this and I'm amazed how efficient the compiler (VS 2017 community) handles it. The compilation is very fine-grained. Each function is handled individually, both regarding need for recompilation and reevaluation of inlining.
A typical build output can look like this (after a code change somewhere),
Code:
1>------ Build started: Project: mint10, Configuration: Release Win32 ------
1>winmain.cpp
1>Generating code
1>191 of 6922 functions ( 2.8%) were compiled, the rest were copied from previous compilation.
1> 0 functions were new in current compilation
1> 16 functions had inline decision re-evaluated but remain unchanged
1>Finished generating code
1>mint10.vcxproj -> E:\Mint\mint10\Release\mint10.exe
1>mint10.vcxproj -> E:\Mint\mint10\Release\mint10.pdb (Full PDB)
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
The only .cpp file is winmain which holds the program entry point and the rest are include (.h) files. WTL is used but that's also include files only. The whole program is one translation unit. The build takes just a few seconds.
The compiler has so much more information about the program than the programmer. The idea that a programmer could and should "help" the compiler doing its job is simply laughable today. Education should stop teaching C++ 89 and dated conventions.
Re: Classes and Constructors
Quote:
Include guards will always be necessary because otherwise a violation of the One Definition Rule (ODR) will occur sooner or later for sure.
yes - and then introduce it :) There's also #pragma once that can be used with compilers such as VS - which IMO is more elegant if supported.
Quote:
You often see in forums like this how they proudly present meticulously split code when the only thing it accomplishes is making the code more complicated to follow.
Yes :)
Quote:
Education should stop teaching C++ 89 and dated conventions.
Definitely! :thumb:
PS and if templates are used, they can't be split between different .h and .cpp files anyhow! The STL is basically just a collection of header files.
Re: Classes and Constructors
Thank you so much 2kaud! I'll definitely read over those websites because the C++ book that I have now is nothing but confusion.