Why have I got a memory exception from making calls to constructors in from my class?
Jul 21, 2020 at 9:53pm UTC
Hello
I have the task of developing a class for students at university. I call the constructor of the object, creating it with some assigned values. Then I get an exception thrown each time. Not really sure where the error is
Students.h
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 100 101 102 103 104 105
#pragma
#ifndef STUDENTSDEF
#define STUDENTSHEADERDEF
#include <string>
#include <iostream>
using namespace std;
class Student
{
public :
string mName;
double mlibrary_Fine;
double mtuition_Fees;
//Default Constructor
Student();
//over-ridden constructor
Student(string, double , double );
//Copy constructor
Student(Student&);
//Destructor
~Student();
//Assignment operator
Student& operator =(const Student&);
//Copy Constructor
void showStudent(Student&);
double totalMoneyOwed(double , double );
void enterDetails(Student);
};
//Default constructor
Student::Student()
{
mName = "John" ;
mlibrary_Fine = 0.0;
mtuition_Fees = 0.0;
}
//Over-ridden constructor
Student::Student(string Name, double fines, double fees)
{
mName = Name;
mlibrary_Fine = fines;
mtuition_Fees = fees;
}
//Copy Constructor
Student::Student(Student& otherStudent)
{
otherStudent.mName = mName;
otherStudent.mlibrary_Fine = mlibrary_Fine;
otherStudent.mtuition_Fees = mtuition_Fees;
}
Student& Student::operator =(const Student& anotherStudent)
{
mName = anotherStudent.mName;
mlibrary_Fine = anotherStudent.mlibrary_Fine;
mtuition_Fees = anotherStudent.mtuition_Fees;
return *this ;
}
Student::~Student()
{
delete [] &mName;
delete [] &mlibrary_Fine;
delete [] &mtuition_Fees;
}
void Student::showStudent(Student& student)
{
cout << "Name of student = " << student.mName << endl;
cout << "Library Fines = " << student.mlibrary_Fine << endl;
cout << "Fees = " << student.mtuition_Fees << endl;
}
double Student::totalMoneyOwed(double libfine, double fees)
{
double total;
total = libfine + fees;
return total;
}
void Student::enterDetails(Student student)
{
cout << "What is the name of the student?" << endl;
getline(cin, student.mName);
cout << "What is the total fines for the student?" << endl;
cin >> student.mlibrary_Fine;
cout << "What are the total fees for the student ?" << endl;
cin >> student.mtuition_Fees;
}
#endif
Main CPP
1 2 3 4 5 6 7 8 9 10 11 12 13
#include <iostream>
#include <string>
#include "Students.h"
using namespace std;
int main()
{
Student A("Dude" , 1.0, 1.0);
A.showStudent(A);
A.~Student();
return 0;
}
Jul 21, 2020 at 10:28pm UTC
Please explain your copy constructor and destructor.
Jul 22, 2020 at 10:46am UTC
Hi,
for the copy constructor, I just want to be able to copy over the variables, by reference in this case when creating a new object.
1 2 3 4 5 6 7
//Copy Constructor
Student::Student(Student& otherStudent)
{
otherStudent.mName = mName;
otherStudent.mlibrary_Fine = mlibrary_Fine;
otherStudent.mtuition_Fees = mtuition_Fees;
}
For the destructor, I would just like to delete the instance of the object.
1 2 3 4 5 6
Student::~Student()
{
delete [] &mName;
delete [] &mlibrary_Fine;
delete [] &mtuition_Fees;
}
Jul 22, 2020 at 10:55am UTC
Only call delete on a pointer that was created using new.
mName wasn't. mName is a string object that wil be destroyed when the instance of the class is.
mlibrary_Fine wasn't.
mtuition_Fees wasn't.
The destructor should be empty in this class.
There is nothing in this class that needs delete called on it. Don't call delete on anything that didn't come from new.
A.~Student();
The cases where you should manually call the destructor are very very very few. Definitely not here. When the object goes out of scope, it will be tidied up for you. That's how C++ works. The destructor will be called for you for this object
Student A
1 2 3 4 5 6
void Student::showStudent(Student& student)
{
cout << "Name of student = " << student.mName << endl;
cout << "Library Fines = " << student.mlibrary_Fine << endl;
cout << "Fees = " << student.mtuition_Fees << endl;
}
This function makes no sense. Why pass the object a reference to itself? The object IS itself. Should be written:
1 2 3 4 5 6
void Student::showStudent()
{
cout << "Name of student = " << mName << endl;
cout << "Library Fines = " << mlibrary_Fine << endl;
cout << "Fees = " << mtuition_Fees << endl;
}
Are these the right way round? Looks like you overwrite otherStudent, instead of overwrite the object you're copying to.
1 2 3 4 5 6 7
//Copy Constructor
Student::Student(Student& otherStudent)
{
otherStudent.mName = mName;
otherStudent.mlibrary_Fine = mlibrary_Fine;
otherStudent.mtuition_Fees = mtuition_Fees;
}
Last edited on Jul 22, 2020 at 11:20am UTC
Jul 22, 2020 at 1:12pm UTC
Hi,
So here are my revisions.
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 100 101 102 103 104 105 106 107 108 109 110 111 112 113
#pragma
#ifndef STUDENTSDEF
#define STUDENTSHEADERDEF
#include <string>
#include <iostream>
using namespace std;
class Student
{
public :
string mName;
double mlibrary_Fine;
double mtuition_Fees;
//Default Constructor
Student();
//over-ridden constructor
Student(string, double , double );
//Copy constructor
Student(const Student&);
//Destructor
~Student();
//Assignment operator
Student& operator =(const Student&);
//To show the details of the student as output.
void showStudent();
//Method to calculate the total money.
double totalMoneyOwed(double , double );
//Method to enter the details of the student.
void enterDetails();
};
//Default constructor
Student::Student()
{
mName = "John" ;
mlibrary_Fine = 0.0;
mtuition_Fees = 0.0;
}
//Over-ridden constructor
Student::Student(string Name, double fines, double fees)
{
mName = Name;
mlibrary_Fine = fines;
mtuition_Fees = fees;
}
//Copy Constructor
Student::Student(const Student& otherStudent)
{
Student A;
mName = otherStudent.mName;
mlibrary_Fine = otherStudent.mlibrary_Fine;
mtuition_Fees = otherStudent.mtuition_Fees;
}
//Overloading the assignment operator.
Student& Student::operator =(const Student& anotherStudent)
{
mName = anotherStudent.mName;
mlibrary_Fine = anotherStudent.mlibrary_Fine;
mtuition_Fees = anotherStudent.mtuition_Fees;
return *this ;
}
//Destructor
Student::~Student()
{
}
//Method to show details of the student.
void Student::showStudent()
{
cout << "Name of student = " << mName << endl;
cout << "Library Fines = " << mlibrary_Fine << endl;
cout << "Fees = " << mtuition_Fees << endl;
}
//Method to calculate the total money owed by the student.
double Student::totalMoneyOwed(double libfine, double fees)
{
double total;
total = libfine + fees;
return total;
}
//Method to change the member variables of the student object.
void Student::enterDetails()
{
cout << "What is the name of the student?" << endl;
getline(cin, mName);
cout << "What is the total fines for the student?" << endl;
cin >> mlibrary_Fine;
cout << "What are the total fees for the student ?" << endl;
cin >> mtuition_Fees;
}
#endif
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
#include <iostream>
#include <string>
#include "Students.h"
using namespace std;
int main()
{
Student A("Dude" , 1.0, 1.0);
A.showStudent();
A.enterDetails();
A.showStudent();
return 0;
}
Jul 22, 2020 at 1:31pm UTC
Your code is working just fine for me:
https://onlinegdb.com/B1VDyTrgP
Furthermore, there are a few problems with your header file.
#pragma
Why do you have a pragma here with nothing following it? You most likely meant to use #pragma once, but since you use include guards later, this would be unneccesary.
1 2
#ifndef STUDENTSDEF
#define STUDENTSHEADERDEF
Your #ifndef and #define don't use the same symbol. This is not how to use include guards.
Jul 22, 2020 at 2:35pm UTC
1 2 3 4 5 6 7 8 9
//Copy Constructor
Student::Student(const Student& otherStudent)
{
Student A; // Who is A? Why is she here?
mName = otherStudent.mName;
mlibrary_Fine = otherStudent.mlibrary_Fine;
mtuition_Fees = otherStudent.mtuition_Fees;
}
I do recommend reading about
member initializer list syntax too.
See
https://www.learncpp.com/cpp-tutorial/8-5a-constructor-member-initializer-lists/
1 2 3 4 5 6
Student::Student(const Student& otherStudent)
: mName( otherStudent.mName ),
mlibrary_Fine( otherStudent.mlibrary_Fine ),
mtuition_Fees( otherStudent.mtuition_Fees )
{
}
Last edited on Jul 22, 2020 at 2:36pm UTC
Topic archived. No new replies allowed.