Constructor vs default constructor - c++

I'm an aspiring software engineer and full-time CS student. During the holiday break, I have been working on exercises to be better at my craft (C++). There are topics that I just need some clarity on. I'm working on a Target Heart Rate Calculator.
I have spent hours, days, trying to understand the concept of the constructor vs default constructor. I know that a constructor is required for every object created.
Before going any further, I want to test my code where it prompts the user to enter their first name and then return it. For once and for all, for the slow learners out there struggling including myself, can anyone please just explain this in Layman's terms with a visual explanation, please?
Below is my code. I'm receiving an error:
no matching function for call to 'HeartRates::HeartRates()'
main.cpp
int main() {
HeartRates patient;
cout << "First name: ";
string firstName;
cin >> firstName;
patient.setFirstName(firstName);
patient.getFirstName();
return 0;
HeartRate.h
// create a class called HeartRates
class HeartRates {
public:
// constructor receiving data
HeartRates(string personFirstName, string personLastName, int month, int day, int year) {
firstName = personFirstName;
lastName = personLastName;
birthMonth = month;
birthDay = day;
birthYear = year;
}
void setFirstName(string personFirstName) {
firstName = personFirstName;
}
string getFirstName() {
return firstName;
}
private:
// attributes
string firstName, lastName;
int birthMonth, birthDay, birthYear;
};
Thank you, everyone! Sheesh! My book adds all these extra words that aren't necessary and makes the reading hard. All it had to say was:
If you want to create an object to receive information from a user, make sure your constructor has empty (). If you have data to input manually, pass that data through your constructor's parameters.
I hope this was the guise of your explanation. I love this community - thank you so much! You all have no idea about my back story - basically transitioning from a 15 years marketing/advertising career to becoming a software engineer. You all have been so welcoming and it confirms I made a great decision to switch.๐Ÿ™Œ๐ŸฝโœŠ๐Ÿฝ๐Ÿค๐Ÿฝ๐Ÿ™๐Ÿฝ
Here is my updated code:
main.cpp
int main() {
HeartRates patient;
cout << "First name: ";
string firstName;
cin >> firstName;
patient.setFirstName(firstName);
cout << patient.getFirstName();
return 0;
}
HeartRates.h
// create a class called HeartRates
class HeartRates {
public:
// constructor receiving data - THANKS STACKOVERFLOW COMMUNITY
HeartRates() {
firstName;
lastName;
birthMonth;
birthDay;
birthYear;
}
void setFirstName(string personFirstName) {
firstName = personFirstName;
}
string getFirstName() {
return firstName;
}
private:
// attributes
string firstName, lastName;
int birthMonth, birthDay, birthYear;
};

If you don't define any constructor, you get a constructor that takes no arguments.
As soon as you defined a constructor that has arguments, your no-args constructor retired to the North Pole.
So now you must write HeartRate("first", "last", 1, 1, 2001)
If you don't want to write that, delete the parameter list from your constructor and just set whatever you want for initial values.

Default constructor is any constructor that can be called with no arguments.
MyClass() - default
MyClass(int x) - not default
MyClass(int x = 42) - default
If you don't define any constructor for your class, a compiler generates a default constructor automatically. It looks more or less like MyClass() {}.
HeartRates patient; tries to call a default constructor, since you didn't provide any arguments (that would be HeartRates patient(...);).

The difference between a default constructor and "normal" constructor is simpler than it may seem.
As long as you don't specify the constructor in your class, when creating an object of an class, it always will call the default constructor, which, if you haven't implemented one, will do nothing but creating an object of that specific class with nothing initialized. If you now have implemented your own constructor, with some parameters, the only way to construct an object of that class will require you to call the implemented constructor. Your default constructor is then overwritten.
You can imagine it as a function you only defined. Something like this:
(the function foo is in this example as your constructor)
There is always a
void foo();
function
Whenever you call foo() it will call that specific function doing nothing. And the function foo() is alway given. If you now declare a second foo function like this:
void foo(std::string name)
{
std::cout << "This is the name " << name << std::endl;
}
and you call your foo function, it will then call the new foo function that you have implemented.
Long story short, if you only have created a class with no customized constructor, you always have a default constructor that is been called when creating an object, but not really initializing something. Whenever you write your own customized constructor, it will overwrite the default constructor.

Related

Static class variable initializing to 100 by itself

This is my first question on here, so excuse me if I've formatted everything in a wrong way.
So, to get to the problem - this is s university assignment of mine. The goal is to create a class called Student, which has a few fields, and store the instances in an array of Student objects. One of the tasks is to have a static variable inside the class that keeps track of how many Student instances have been created. To clarify, I have a getData() method that asks the user for the values, and then sets the current object's values to those entered (basically just like a constructor, which makes the constructors obsolete, but they want us to do it that way for some reason). In the getData() function, the static count variable gets raised by 1, as well as in the constructors, and gets decremented in the destructor.
The issue is that for some reason, Student::amount variable sets itself to 100. Every time that i try to access it from the main() function, its 100 plus the amount of students created, so if we have created 2 students, Student::amount will be equal to 102. I've nowhere explicitly set it to that number, which also matches the size of the array, by the way.
I'm still rather new to C++, I've read and watched some material on how OOP works here, but I've barely even scratched the surface.
Sorry again if my question is badly formulated or/and badly formatted, and I hope you can help me with this!
#include <iostream>
#include <string>
using namespace std;
class Date {
...
};
class Student {
// Fields
private:
string name = "";
string PID = "";
int marks[5]{ 0 };
short course = 0;
public:
// Count of all students
static int amount;
// Getters
...
// Setters
...
// Constructors
Student(); // Default one, Student::amount gets raised by 1 there
Student(string name, string PID, int marks[5], short course);
// Destructor
~Student();
// Methods
void getData();
void display(); // Display the information of a student
};
// Array of students
Student students[100];
// Student::Count
int Student::amount; // Initializes with 0 if not explicitly initialized
void Student::getData() {
cin.ignore();
cout << "\nName: "; getline(cin, name);
cout << "PID: "; getline(cin, PID);
cout << "Marks:\n";
for (int i = 0; i < 5; i++)
{
cin >> marks[i];
}
cout << "Course: "; cin >> course;
Student::amount++;
}
Student::Student(string name, string PID, int marks[5], short course) {
this->setName(name);
this->setPID(PID);
this->setMarks(marks);
this->setCourse(course);
Student::amount++;
}
The global declaration Student students[100]; calls the default Student constructor 100 times, before main is reached. According to your comment (you don't supply the constructor implementation), that constructor increases amount by 1.
A solution here is to remove Student::amount and instead use
std::vector<Student> students;
students.size() will give you the number of students in that container. Use push_back to put students into the vector.
A very crude alternative that at least is broadly compliant with the question constraints is to remove the amount increment from the default constructor, and all other places apart from the four argument constructor.

Classes: compiler error ยซno matching function for call to "constructor"ยป

I'm new to C++ (and stackoverflow, also). Unfortunately I don't personally know anyone who knows C++, thus the following question may be too simple to answer. However I wouldn't post it if I could ask a friend to look at my code. I'm really desperate here.
So, basically I'm trying to link 3 classes: Course, Teacher, Student. Teacher and Student classes "live" inside the Course. However, when I create a Teacher object inside Course a compiler error pops up: "no matching function for call to Teacher::Teacher()".
I can not really see any error, and I can't really grasp the compiler message. Please find my code below. I'm sorry for the wall of code, I tried to suppress as much as I could.
I'm open to any comment and criticism.
Thank you very much in advance.
class Teacher
{
private:
string fName;
string lName;
int age;
string address;
string city;
string phone;
public:
// Constructor & destructor
Teacher(string fName, string lName);
~Teacher();
// Setters & getters
void setName(string fNameIn, string lNameIn);
void getName();
void setAge(int ageIn);
void getAge();
void setAddress(string addressIn);
void getAddress();
void setCity(string cityIn);
void getCity();
void setPhone(string phoneIn);
void getPhone();
void GradeStudent(); // outputs an appropriate message to the console such as "Student graded"
void SitInClass(); // outputs "Sitting at front of class" for the teacher and "Sitting in main theater" for the students.
};
Teacher::Teacher(string fNameIn, string lNameIn)
{
fName = fNameIn;
lName = lNameIn;
//age = 0;
}
class Course
{
private:
string name;
Student students;
Teacher teacher;
public:
// Constructors & destructor
Course(string nameCourseIn);
//Course(string nameCourseIn, Student studentVecIn, Teacher teacherIn);
~Course();
// Setters and getters
void setName(string courseNameIn);
void getName();
void setClass(Student studentVecIn);
void setTeacher(Teacher teacherIn);
};
int main()
{
std::string name = "Intermediate C++";
Course course (name);
course.getName();
return 0;
}
You have explicitly defined a constructor for Teacher, meaning that is the only constructor that exists. In order to have a default parameter-less constructor for you to use in Course, you must first implement one.
Adding Teacher(); to your Teacher.h and Teacher::Teacher(){} to Teacher.cpp will solve your problem, however your Teacher within the Course will need to be initialised manually.
EDIT:
Badr El Hiouel kindly pointed out that in the case where you do not wish to execute any code in the default constructor, and you're using C++11, you can simply add Teacher() = default to Teacher.h, omitting it from the .cpp altogether.

Passing arguments to objects in C++ - Please explain the logic behind this? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I started learning C++ and now I am lost, I don't see the logic in this. simply does not make sense to me how it is possible that I can add arguments to an object and then those arguments are used by the program. Sure I can memorize this feature, but can someone please explain the logic behind this? Everything else in C++ makes sense, I guess this probably does too, only I don't see it.
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
class Person{
private:
string name;
int age;
public:
Person(){
name = "undefined";
age = 0;
};
Person(string newname){
name = newname;
age = 0;
};
Person(string newname, int newage){
name = newname;
age = newage;
};
string toString(){
stringstream ss;
ss << "Name is: " << name << " Age is : " << age;
return ss.str();
};
};
int main()
{
Person person1;
Person person2("David"); // I don't get this ???
Person person3("Mia", 35); // // I don't get this ???
cout << person1.toString() << endl;
cout << person2.toString() << endl;
cout << person3.toString() << endl;
return 0;
};
You are actually calling the constructors when you say you're passing arguments to objects. Constructors with matching signatures are called.
When you write Person person1;, default constructor which is
Person(){
name = "undefined";
age = 0;
};
is called.
When you write Person person2("David");,
Person(string newname){
name = newname;
age = 0;
};
is called.
And finally, when you do Person person3("Mia", 35);,
Person(string newname, int newage){
name = newname;
age = newage;
};
is called.
This statement: Person person1; is calling this constructor:
Person();
This Person person2("David"); is calling this constructor:
Person(string newname);
And this Person person3("Mia", 35); is calling this constructor:
Person(string newname, int newage);
Since constructors are functions that initialize the object of class Person, they can receive arguments, like any function.
When you define a new C++ class, with its members as your choice, each one of these functions as a regular variable (or pointers, or instances of other classes, etc.) which is a concept you are already familiar with.
So when you instantiate a new instance of the class, the compiler knows exactly how much memory it should allocate, and what is the inner structure of it - how to divide that memory into smaller pieces corresponding to the class members.
And that is how, when you call a constructor, it knows how to "add the arguments" to your instance.

Copy constructor with reference counting

I am trying to implement reference counting. Every copy of object should increment the counter for it.
My code looks
class Person{
public:
struct Kids{
Kids(){
count = 2;
boy = "Alex";
girl= " Lisa";
}
int count;
string boy;
string girl;
};
Person( string name , int age){
this -> name = name;
this -> age = age;
}
Person( const Person& a){
one = a.one;
one -> count++;
age = a.age;
name = a.name;
for( int i = 0; i < 5; i++){
family[i] = a.family[i];
}
};
void PrintIt(){
cout << one -> count << endl;
}
private:
Kids *one;
string name;
int age;
Kids family[5];
};
int main(){
Person one("Jogn",50);
//return 0;
Person two(one);
two.PrintIt();
}
And it throws seg fault. I have tried to pass object to copy constructor as a pointer , which resulted in the same output. How can create a copy constructor ,that will point to object via pointers , which will result in possible reference counting?
Have you tried std::shared_ptr, it is available in C++ 11. This template class has the advantages of being well tested and already developed. Here you have a link to the documentation.
Kids *one;
Seems to be uninitialized. When you copy a value to it. this value is also unitialized, since it is private, and i don't see any init code for it. You have to add something like
kids(new Kids())
in Person constructor which is not copy one.
ps. don't forget operator= and destructor.
just make a static variable in private and outside your class initialize it to zero using the scope resolution operator. Then inside your constructor increment it by one. Each time you will make an object its constructor will be called and the static variable will be incremented by one. Then when ever you want you can display that variable where ever you want (again by using scope resolution operator).

Difference between constructor and default constructor

I'm writing the following program.
Write a class called CAccount which contains two
private data elements, an integer accountNumber
and a floating point accountBalance, and three
member functions:
A constructor that allows the user to set
initial values for accountNumber and
accountBalance and a default constructor
that prompts for the input of the values for
the above data members.
A function called inputTransaction,
which reads a character value for
transactionType ('D' for deposit
and 'W' for withdrawal), and a floating point
value for transactionAmount, which
updates accountBalance.
A function called printBalance, which
prints on the screen the accountNumber
and accountBalance.
--
#include <iostream>
using namespace std;
class CAccount{
public:
CAccount(){
setValues(2, 5);
printBalance();
inputTransaction();
printBalance();
}
void setValues(int aN, int aB);
void inputTransaction();
void printBalance();
private:
int accountNumber;
float accountBalance;
};
void CAccount::setValues(int aN, int aB){
accountNumber = aN;
accountBalance = aB;
}
void CAccount::inputTransaction(){
char transactionType;
float transactionAmount;
cout << "Type of transaction? D - Deposit, W - Withdrawal" << endl;
cin >> transactionType;
cout << "Input the amount you want to deposit/withdraw" << endl;
cin >> transactionAmount;
if(transactionType == 'D'){
accountBalance += transactionAmount;
}
else if(transactionType == 'W'){
accountBalance -= transactionAmount;
}
}
void CAccount::printBalance(){
cout << "Account number : " << accountNumber << endl << "Account balance : " << accountBalance << endl;
}
int main ()
{
CAccount client;
}
I don't understand this part :
1. A constructor that allows the user to set
initial values for accountNumber and
accountBalance and a default constructor
that prompts for the input of the values for
the above data members.
What exactly is the difference between a constructor and default constructor, I'm kinda confused on this step.
Other than that, I would like to ask people with more experience to tell me any tips I should follow when coding with classes and which mistakes to avoid (this is my first class I ever wrote in C++).
A Default constructor is defined to have no arguments at all as opposed to a constructor in general which can have as many arguments as you wish.
Your second question is far too general to be answered here. Please turn to the many many sources in the net. stackoverflow is for specific questions not for tutorials.
If you don't define a constructor for a class, a default parameterless constructor is automatically created by the compiler. Default constructor is created only if there are no constructors. If you define any constructor for your class, no default constructor is automatically created.
A default constructor is one that doesn't need to be given arguments, either because it doesn't have any, or the ones it has have default values. Such constructors are special in the sense that say Type var; or Type var[10];
or new Type(); invoke and require them.
See how you've written void CAccount::setValues(int aN, int aB)? If you change setValues to CAccount it becomes another constructor with 2 int arguments... that's a user-defined non-default constructor and satisfies your requirements.
As is, because you only have one constructor that doesn't take any arguments but reads inputs from stdin, you're forcing users to use that constructor, read inputs, and if you call setValues you'd be overwriting those values with the setValue arguments....
Default constructor is one type of constructor.
Where as we have other conctructors namely:
Parameterised constructor
Copy constructor
If we don't define any constructor then a default constructor is provided. But if we define any constructor then no default constructor is provided.
Default constructor doesn't take any parameter. Where as other constructors need parameter.
For your 2nd question:
If you define any constructor (parameterised or copy constructor) then you should define a default constructor also. Otherwise code like
ClassName obj = new ClassName();
will give build error. But this again depends upon your requirement and usecase.
And constructor is generally used for initialization. But you have called some functions inside constructor which is generally not done.
The default constructor is a compiler generated parameter-less constructor. You can explicitly define a constructor taking zero arguments but not everybody would call it a default constructor.
Your program should define a constructor with parameters for accountNumber and accountBalance, and a parameter-less one that prompts the user. Like this:
#include <iostream>
using namespace std;
class CAccount {
public:
/**
* Constructor prompting the user for accountNumber and accountBalance
*/
CAccount()
{
inputTransaction();
printBalance();
}
/**
* Constructor initializing accountNumber and accountBalance with parameters
*/
CAccount(int accountNumber, float accountBalance)
: accountNumber(accountNumber),
accountBalance(accountBalance)
{
printBalance();
}
void inputTransaction() { /* Implement me. */ }
void printBalance() { /* Implement me. */ }
private:
int accountNumber;
float accountBalance;
};
As you can see, I used initializers for accountNumber and accountBalance in the constructor taking those arguments. That is what you should always do.