C++ class object default constructor bug - c++

I am trying to create a class object s2 with some customized attributes and some attributes from default constructor however my output is the wrong output for the get_year function. It should be outputing 0 which is the key for FRESHMAN but it is out putting 2 instead. The rest of the code is outputting as expected:
#include <stdio.h>
#include <iostream>
#include <algorithm> // for std::find
#include <iterator> // for std::begin, std::end
#include <ctime>
#include <vector>
#include <cctype>
using namespace std;
enum year {FRESHMAN, SOPHOMORE, JUNIOR, SENIOR};
struct name
{
string firstName;
string lastName;
friend std::ostream& operator <<(ostream& os, const name& input)
{
os << input.firstName << ' ' << input.lastName << '\n';
return os;
}
};
class Student: name{
private:
name Name;
year Year;
int idNumber;
string Department;
public:
void setname(string fn="", string ln="")
{
Name.firstName =fn;
Name.lastName =ln;
}
name get_name()
{
return Name;
}
void set_year(year yr=FRESHMAN)
{
Year=yr;
}
year get_year()
{
return Year;
}
void set_ID(int ID=0)
{
idNumber=ID;
}
int get_ID()
{
return idNumber;
}
void set_Department(string Dept="")
{
Department=Dept;
}
string get_Department()
{
return Department;
}
};
int main()
{
Student s2;
s2.setname("Nikolai", "Khabeboolin");
s2.set_ID(12436193);
cout<<"ID is: "<< s2.get_ID()<<", name is "<< s2.get_name()<<", year in school is: "<<s2.get_year()<<", Department is "<<s2.get_Department()<<endl;
return 0;
}

Student lacks a constructor, so all its members are default initialized, and the default initialization of year Year and int idNumber is "no initialization", so reading from them is undefined behavior. Reading them might find 0, 2, a random value each time, or crash.
I see that your class contains a void set_year(year yr=FRESHMAN) member, but your code never called set_year, so no part of this executed.
You should make a default constructor for Student, or as Goswin von Brederlow stated, use year Year{FRESHMAN}; and int idNumber{-1}; when declaring the members, to give them default initializations.

By not explicitly declaring and defining a constructor, in this case Student(), you open yourself up to undefined behavior. Your constructor should call set_year(year yr=FRESHMAN) OR even better, just set the year itself.

Related

C++ code -calling a constructor of one class within a constructor of same class

I am trying to compile this C++ code unfortunately, I failed to compile the code below. Can you help me by explaining why I am getting this error ?
#include <iostream>
#include <cstring>
using namespace std;
class student
{
private:
char name[10];
int id;
int fee;
public:
student(char name[10],int id)
{
strcpy(this->name,name); //string copy
this->id=id;
fee=0;
}
student(char name[10],int id,int fee)
{
student::student(name,id); //calling a constructor of one class
// within a constructor of same class
this->fee=fee;
}
void show() //print function
{
cout<<"Name:"<<name<<endl;
cout<<"id:"<<id<<endl;
cout<<"fee:"<<fee<<endl<<endl;
}
};
int main()
{
student s1("DAVID",123);
student s2("WILLIAM",124,5000);
s1.show();
s2.show();
return 0;
}
Below is the error GCC is complaining about.:
main.cpp|20|error: cannot call constructor 'student::student' directly [-fpermissive]|
As rightly suggested by #sweenish, You must do the constructor delegation in the initialization section. Something like this:
#include <iostream>
#include <cstring>
using namespace std;
class student
{
private:
char name[10];
int id;
int fee;
public:
student(char name[10],int id)
{
strcpy(this->name,name); //string copy
this->id=id;
fee=0;
}
student(char name[10],int id,int fee): student(name, id) // constructor delegation
{
this->fee=fee;
}
void show() //print function
{
cout<<"Name:"<<name<<endl;
cout<<"id:"<<id<<endl;
cout<<"fee:"<<fee<<endl<<endl;
}
};
int main()
{
student s1("DAVID",123);
student s2("WILLIAM",124,5000);
s1.show();
s2.show();
return 0;
}
Also, an advice for you. You may define the more specialized constructor and delegate the responsibility of less specialized constructors to more specialized ones.
#include <iostream>
#include <cstring>
using namespace std;
class student
{
private:
char name[10];
int id;
int fee;
public:
student(char name[10],int id, int fee): id{id}, fee{fee} // more specialized
{
strcpy(this->name,name); //string copy
}
student(char name[10],int id): student(name, id, 0) { } // less specialized calling the more specialized constructor
void show() //print function
{
cout<<"Name:"<<name<<endl;
cout<<"id:"<<id<<endl;
cout<<"fee:"<<fee<<endl<<endl;
}
};
int main()
{
student s1("DAVID",123);
student s2("WILLIAM",124,5000);
s1.show();
s2.show();
return 0;
}
Here's your code with changes made to get it compiling; I marked the changes with comments.
#include <iostream>
// #include <cstring> // CHANGED: Prefer C++ ways when writing C++
#include <string> // CHANGED: The C++ way
// using namespace std; // CHANGED: Bad practice
class student {
private:
std::string name{}; // CHANGED: Move from C-string to std::string
int id = 0; // CHANGED: Default member initialization
int fee = 0;
public:
// CHANGED: Move from C-string to std::string
student(std::string name, int id)
: name(name),
id(id)
// CHANGED: ^^ Utilize initialization section
{
// CHANGED: Not needed anymore
// strcpy(this->name,name); //string copy
// this->id=id;
// fee=0;
}
student(std::string name, int id, int fee) : student(name, id) {
// CHANGED: Not needed anymore
// student::student(name,id); //calling a constructor of one class
// // within a constructor of same class
// NOTE: Inconsistency with other ctor w.r.t. this->
this->fee = fee;
}
void show() // print function
{
std::cout << "Name:" << name << '\n';
std::cout << "id:" << id << '\n';
std::cout << "fee:" << fee << "\n\n";
}
};
int main() {
student s1("DAVID", 123);
student s2("WILLIAM", 124, 5000);
s1.show();
s2.show();
return 0;
}
Here is the same code, but with the stuff I commented out removed to make it easier to read.
#include <iostream>
#include <string>
class student {
private:
std::string name{};
int id = 0;
int fee = 0;
public:
student(std::string name, int id) : name(name), id(id) {}
student(std::string name, int id, int fee) : student(name, id) {
this->fee = fee;
}
void show()
{
std::cout << "Name:" << name << '\n';
std::cout << "id:" << id << '\n';
std::cout << "fee:" << fee << "\n\n";
}
};
int main() {
student s1("DAVID", 123);
student s2("WILLIAM", 124, 5000);
s1.show();
s2.show();
return 0;
}
The initialization section follows the parameter list and is marked with :. You then initialize each member, in the order they are declared.
In the case of the constructor doing the delegating, you are unable to initialize fee in the initialization section. The error I receive is a delegating constructor cannot have other mem-initializers.
I don't like splitting my initialization like that, and if you insist on delegating constructor calls for this class, implement the most specific constructor and delegate to it with your less specific constructors. I prefer default member initialization as I think it leads to less confusion and written code overall.
The code then compiles and you get the expected output:
Name:DAVID
id:123
fee:0
Name:WILLIAM
id:124
fee:5000

Class contains no member named ... in C++

Assuming I am making a library of books in C++ this way:
#include <iostream>
#include <string>
#include <vector>
class Book
{
public:
Book(string name, string author)
};
Simple, just a constructor, now I create a vector of Book and push books back:
int main()
{
vector<Book> books;
books.push_back(Book("Gatsby", "Fitzgerald"));
But when I try to print out some member (name or author):
cout << books[0].name << endl;
return 0;
}
My boy compiler is angry:
error: ‘__gnu_cxx::__alloc_traits >::value_type {aka class Book}’ has no member named ‘name’
cout << books[0].name << endl;
I'm a relative beginner, does this approach make sense at all? And if it does, what did I do wrong?
Thank you!
The class Book has no members to store name and author. And, the constructor that you defined is syntactically wrong.
With public data members, it would look like this:
class Book
{
public:
// data members
std::string name;
std::string author;
// parameterized constructor
Book( std::string name, std::string author )
{
this->name = name;
this->author = author;
}
};
Please note that:
exposing data members like that is in violation of data-hiding principle of OOP. Ideally, the data members should be private and adequate accessor methods should be used.
the assignments of name and author in the body of the constructor is just for your understanding. If you've already studied the initializer list for constructor then use that.
Here's an example (live):
#include <iostream>
#include <string>
#include <vector>
class Book final
{
public:
// constructor with initializer list
Book( std::string name_, std::string author_ ) : name{name_}, author{author_} {}
// accessor methods
std::string getName() const { return name; }
std::string getAuthor() const { return author; }
private:
std::string name;
std::string author;
};
int main()
{
std::vector<Book> books;
books.push_back( Book{"The Alchemist", "Paulo Coehlo"} );
books.push_back( Book{"Fight Club", "Chuck Palahniuk"} );
books.push_back( Book{"No Country for Old Men", "Cormac McCarthy"} );
books.emplace_back( "Brave New World", "Aldous Huxley" );
books.emplace_back( "1984", "George Orwell" );
books.emplace_back( "Animal Farm", "George Orwell" );
for ( const auto& book : books )
{
std::cout << book.getName() << " by " << book.getAuthor() << '\n';
}
return 0;
}
Some relevant threads to read:
Why is "using namespace std;" considered bad practice?
push_back vs emplace_back
range-for loop
C++: "std::endl" vs "\n"

Having Problem for Object Initialization by Constructor in C++ [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I want to create a Student object in C++ and it has the properties of name, major, age and id. The object initialization will be done in the main() part and Student object has the get and set methods for all the constructors. I want to print the student objects in the main() part but I get this error:
in C++98 's1' must be initialized by constructor, not by '{...}'
I am using GNU GCC Complier in Codeblocks. I haven't written specifically any code for compiling or debugging.
I tried to initialize the objects by assigning them to this, making them null, giving them zero and random values but they haven't worked.
Student.h file
#ifndef STUDENT_H
#define STUDENT_H
#include <iostream>
#include <string>
using namespace std;
class Student
{
public:
string name, major;
int age, id;
Student(string name, string major, int age, int id);
string getName();
void setName(string name);
string getMajor();
void setMajor(string major);
int getAge();
void setAge(int age);
int getId();
void setId(int id);
};
ostream & operator << (ostream &out, Student &s);
#endif // STUDENT_H
Student.cpp file
#include "Student.h"
#include <iostream>
using namespace std;
Student::Student(string newName, string newMajor, int newAge, int newId)
{
name = newName;
major = newMajor;
age = newAge;
id = newId;
}
string Student::getName(){
return name;
}
void Student::setName(string newName){
name = newName;
}
string Student::getMajor(){
return major;
}
void Student::setMajor(string newMajor){
major = newMajor;
}
int Student::getAge(){
return age;
}
void Student::setAge(int newAge){
age = newAge;
}
int Student::getId(){
return id;
}
void Student::setId(int newId){
id = newId;
}
ostream & operator << (ostream &out, Student &s)
{
out << "Name: " << s.getName() << " Major: " << s.getMajor() << " Age: " << s.getAge() << " Id:" << s.getId() << endl;
return out;
}
Main.cpp file
#include <iostream>
#include <string>
#include "Student.h"
using namespace std;
int main()
{
Student s1 {"John","MATH",24,123456};
Student s2 {"Steve","ENG",22,654321};
cout << s1 << endl;
cout << s2 << endl;
return 0;
}
I expect to print out the properties of the students as a list but when I run it the program crashes and I get this error:
** in C++98 's1' must be initialized by constructor, not by '{...}' **
I fixed my problem. There were a few problems so here I will explain my solutions in detail.
1-My code is written in C++11 syntax but I was using C++98 syntax so I changed my complier to C++11.
2-My initialization was wrong, I used new variables such as newName, newAge... to change the properties of the Student object.
3-My set methods were wrong so I changed them similar to my initialization.
4-I added an opeator to print out properties more easily.
All the changes are updated for the code in the question

Error with Class in C++ for my project

I am new to this. Basically I just learnt how to use class in C++. When I try to print out, the values just seem to be 0. Can anyone help me out? Its supposed to print out:
Susan Myers 47899 Accounting Vice President
Mark Jones 39119 IT Position
Joy Rogers 81774 Manufacturing Engineer
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
class Employee
{
private:
string name;
int idNumber;
string department;
string position;
public:
Employee()
{
name=" ";
idNumber=0;
department=" ";
position=" ";
}
Employee(string, int, string, string)
{
int id;
string n,d,p;
name=n;
idNumber=id;
department=d;
position=p;
}
Employee(string, int)
{
string n;
int id;
name=n;
idNumber=id;
}
void setName(string)
{
string n;
name=n;
}
void setId(int)
{
int id;
idNumber=id;
}
void setDepartment(string)
{
string d;
department=d;
}
void setPosition(string)
{
string p;
position=p;
}
string getName() const
{
return name;
}
int getId() const
{
return idNumber;
}
string getDepartment() const
{
return department;
}
string getPosition() const
{
return position;
}
};
int main()
{
Employee e1;
Employee e2;
Employee e3;
e1.setName("Susan Meyers");
e2.setName("Mark Jones");
e3.setName("Joy Rogers");
e1.setId(47899);
e2.setId(39119);
e3.setId(81744);
e1.setDepartment("Accounting");
e2.setDepartment("IT");
e3.setDepartment("Manufacturing");
e1.setPosition("Vice President");
e2.setPosition("Programmer");
e3.setPosition("Engineer");
cout<<"---------------------------------------"<<endl;
cout<<"Name"<<setw(6)<<"ID Number"<<setw(10)<<"Department"<<setw(12)<<"Position"<<endl;
cout<<e1.getName()<<setw(6)<<e1.getId()<<setw(10)<<e1.getDepartment()<<setw(12)<<e1.getDepartment()<<endl;
cout<<e2.getName()<<setw(6)<<e2.getId()<<setw(10)<<e2.getDepartment()<<setw(12)<<e2.getDepartment()<<endl;
cout<<e3.getName()<<setw(6)<<e3.getId()<<setw(10)<<e3.getDepartment()<<setw(12)<<e3.getDepartment()<<endl;
return 0;
}
This is what you get when you rely on guesswork rather than properly reading an introductory textbook on C++
A constructor of the Employee class which (apart from a blank line that I've removed) you define as
Employee(string, int, string, string)
{
int id;
string n,d,p;
name=n;
idNumber=id;
department=d;
position=p;
}
has the following effects.
The four arguments passed by the caller are ignored, since they are not named.
Four default-initialised variables (id, n, d, and p) are defined local to the constructor body. id will be uninitialised. The others, since they are std::string, are default-initialised (to an empty string)
The next four statements copy those variables into class members. The result is that initialising idNumber has undefined behaviour (since id is uninitialised) and the three strings are initialised to empty strings.
To get the effect that (I assume) you intend, change this to;
Employee(std::string n, int id, std::string d, std::string p)
{
name=n;
idNumber=id;
department=d;
position=p;
}
Note that I'm calling string by its full name std::string. That allows removing the using namespace std which (among other things) is BAD practice in header files.
Even better, change this to
Employee(const std::string &n, int id, const std::string &d, const std::string &p) :
name(n), idNumber(id), department(d), position(p)
{
}
which passes the strings by const reference (avoids additional copies of std::strings) and uses an initialiser list instead of assigning to members in the constructor.
Similar comments apply to ALL of the member functions of Employee, except that only constructors can have initialiser lists.
Errors made
Presentation
Your code is extremely cluttered, and has much irrelevant stuff.
Syntax
void setPosition(string){
Here your function has no argument! What is string?
Code
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
class Employee{
public:
string name;
int idNumber;
string department;
string position;
void setName(string n){
name=n;
}
void setId(int k){
int id;
idNumber=id;
}
void setDepartment(string d){
department=d;
}
void setPosition(string p){
position=p;
}
string getName(){
return name;
}
int getId(){
return idNumber;
}
string getDepartment(){
return department;
}
string getPosition(){
return position;
}
};
int main(){
Employee e1;
Employee e2;
Employee e3;
e1.setName("Susan Meyers");
e2.setName("Mark Jones");
e3.setName("Joy Rogers");
e1.setId(47899);
e2.setId(39119);
e3.setId(81744);
e1.setDepartment("Accounting");
e2.setDepartment("IT");
e3.setDepartment("Manufacturing");
e1.setPosition("Vice President");
e2.setPosition("Programmer");
e3.setPosition("Engineer");
cout<<"---------------------------------------"<<endl;
cout<<"Name"<<" "<<"ID Number"<<" "<<"Department"<<" "<<"Position"<<endl;
cout<<e1.getName()<<" "<<e1.getId()<<" "<<e1.getDepartment()<<" "<<e1.getPosition()<<endl;
cout<<e2.getName()<<" "<<e2.getId()<<" "<<e2.getDepartment()<<" "<<e2.getPosition()<<endl;
cout<<e3.getName()<<" "<<e3.getId()<<" "<<e3.getDepartment()<<" "<<e3.getPosition()<<endl;
}
Output
---------------------------------------
Name ID Number Department Position
Susan Meyers 32767 Accounting Vice President
Mark Jones 32767 IT Programmer
Joy Rogers 32767 Manufacturing Engineer
Explanation
I have shortened your code by 50%(shows how much redundant stuff you had), and here is a working code.
void setDepartment(string d){
department=d;
}
Here, string d is defined IN the function as an argument. Note that your code also cout<< department twice, and I have corrected that for you in my above code.
Hope this helps.

Could not separate implementation and interface

I am unable to compile the following files.
I am trying to pass the name and age to an object and after checking and assigning each age to proper category(adult, kid...) then i am trying to print it.
My 3 files are following:
The first 1:
//cannot access private member declared in class Person
//No constructor could take the source type, or constructor overload resolution was ambiguous.
#include <iostream>
#include <string>
using namespace std;
#include "person2.h"
void getData(Person&);
void displayData(Person&);
int main(){
Person p;
getData(p);
displayData(p);
}
void getData(Person& p){
cout<< "Enter the name: ";
cin>> p.name;
cout<<"Enter the age: ";
int age;
cin>> age;
p.setAge(age);
p.ageGroup = p.determineAgeGroup(age);
}
void displayData(Person& p){
cout<<p.name<< " is in the group of " << p.ageGroup <<endl;
}
The second one:
#include <iostream>
#include <string>
using namespace std;
class Person {
public:
string name;
string ageGroup;
void setAge(int&);
string getAge();
string getAgeGroup(int);
private:
int age;
string determineAgeGroup(int );
};
The third one:
#include <iostream>
#include <string>
#include "person2.h"
using namespace std;
void Person::setAge(int& a){
if(a<0) cout<< "No";
}
string Person::getAge(){
return age;
}
string Person::determineAgeGroup(int a){
if(a>= 65) return "Senior";
else if(a<65 & a>= 20) return "Adult";
else if(a<20 & a>= 13) return "Teen";
else return "Kid";
}
string Person::getAgeGroup(int a){
return determineAgeGroup(a);<<endl;
}
Check the following:
endl instead of end in displayData
declare int age in getData and pass that value to p.setAge
return value from getAge should be an int
make determineAgeGroup() public or call determineAgeGroup() from a member function like setAge() or call your public function getAgeGroup().
This should at least get you compiling...
Note: The final edit that solved the problem was bullet point number 4, in particular calling the public function getAgeGroup().