Why have I got a memory exception from making calls to constructors in from my class?

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;
}

Please explain your copy constructor and destructor.
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;
}
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
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;
}
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.
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
Topic archived. No new replies allowed.