overloaded assignment operator not working - c++

I have a class Employee. (Some of my comments are not updated from when I added members tasks and taskList; I apologize for that.)
Employee.h
#include <string>
#include <iostream>
using namespace std;
class Employee {
private:
string employee_name;
string employee_ssn;
string * taskList; //stores an array of tasks for the employee to do
int tasks; //stores the number of tasks an employee needs to do
public:
//constructors
Employee(); //default - nothing
Employee(string, string, string a[], int numOfTasks); //sets both ssn and name
~Employee(); //destructor
//copy constructor:
Employee(const Employee &emp);
Employee & operator =(const Employee& source);
void set_name(string); //sets name in program
void set_ssn(string); //sets ssn in program
string get_ssn(); //returns ssn as string
string get_name(); //returns emp name as string
void display(); //displays both on two separate lines
};
Employee.cpp
#include "Employee.h"
//constructors
//default constructor makes the object empty
Employee::Employee() {
taskList = nullptr;
return;
}
//constructor sets both name and ssn
Employee::Employee(string x, string y, string a[], int numOfTasks) {
employee_name = x;
employee_ssn = y;
tasks = numOfTasks;
taskList = a;
return;
}
//destructor
Employee::~Employee() {
delete [] taskList;
}
//copy constructor
Employee::Employee(const Employee & source) {
//copy simple member variables
employee_name = source.employee_name;
employee_ssn = source.employee_ssn;
tasks = source.tasks;
//allocate new dynamic array for taskList
taskList = new string[source.tasks];
//copy values from one taskList to another
for (int i = 0; i < tasks; i++)
taskList[i] = source.taskList[i];
return;
}
//assignment operator overloading
Employee & Employee::operator =(const Employee& source) {
cout << "Calling the assignment operator overloader.\n";
//check for self assignment
if (this == &source)
return *this; //avoid doing extra work
employee_name = source.employee_name;
employee_ssn = source.employee_ssn;
tasks = source.tasks;
cout << "Substituting 'task list'\n";
//delete former taskList
//if (taskList != nullptr)
delete[] taskList;
cout << "TaskList deleted.\n";
//allocate new one with same capacity
taskList = new string[source.tasks];
//copy values from one to the oher
for (int i = 0; i < tasks; i++)
taskList[i] = source.taskList[i];
cout << "Function complete.\n";
return *this;
}
//postcon: name is set to inputted string
void Employee::set_name(string s) {
employee_name = s;
return;
}
//postcon: ssn is set to inputted string
void Employee::set_ssn(string s) {
employee_ssn = s;
return;
}
//returns ssn as string
string Employee::get_ssn() {
return employee_ssn;
}
//returns employee name as string
string Employee::get_name() {
return employee_name;
}
//precon: name and ssn are both assigned
//postcon: name and ssn printed to the screen w/ labels on two lines
void Employee::display() {
cout << "Name: " << employee_name << endl;
cout << "SSN: " << employee_ssn << endl;
cout << "Tasks:\n";
for (int i = 0; i < tasks; i++)
cout << i + 1 << ". " << taskList[i] << endl;
return;
}
We were instructed to implement a copy constructor and assignment overloading, and we were also specifically instructed to make individual Employee objects dynamically allocated in the main program.
What I seem to be having issue with is the swapping using the assignment overload.
employee_driver.cpp
#include "Employee.h"
#include <iostream>
int main() {
//tasks for each employee to do:
//Tasks to be assigned to Marcy:
string tasks[2] = {"Send emails", "Prepare meeting brief"};
//Taks to be assigned to Michael:
string tasks2[3] = {"Stock up on pens", "Send emails", "Organize union"};
Employee *emp1 = new Employee("Marcy", "678091234", tasks, 2);
Employee *emp2 = new Employee("Michael", "123994567", tasks2, 3);
//display data before swap
emp1->display();
cout << endl;
emp2->display();
cout << endl;
//swap employees
Employee temp(*emp1); //using copy constructor to copy first employee into temporary
*emp1 = *emp2;
*emp2 = temp; //uses overloaded assignment operator to copy values of temp into emp2; Marcy's data is now in Michael's pointer
//display after swap
cout << "\n\nAfter swap:\n\n";
emp1->display();
cout << endl;
emp2->display();
//free heap
delete emp1;
delete emp2;
//delete emp3;
return 0;
}
The issue in question seems to occur here:
*emp1 = *emp2; (towards the bottom of the main program), but I cannot figure out why; any help would be appreciated. I could get around it, but I don't think that's the purpose of the exercise, and I would like to know why this statement is not working correctly.
Thanks.

Within the constructor
Employee::Employee(string x, string y, string a[], int numOfTasks) {
employee_name = x;
employee_ssn = y;
tasks = numOfTasks;
taskList = a;
return;
}
you just store the passed pointer a in the data member taskList,
In main the arrays
string tasks[2] = {"Send emails", "Prepare meeting brief"};
//Taks to be assigned to Michael:
string tasks2[3] = {"Stock up on pens", "Send emails", "Organize union"};
were not allocated dynamically. So you may not in the copy assignment operator call the operator delete [] for such arrays
delete[] taskList;
You need in the constructor to allocate dynamically the array a pointer to which is passed as an argument to the constructor.
Also pay attention to that in the default constructor you need to set the data member tasks to 0.

Related

Need help resizing dynamic array - Heap corruption detected

I am working on an assignment for my c++ class and am having trouble with one portion of the class that requires resizing a dynamic array. For this assignment, I need to store terms of a polynomial in a dynamic array. I am specifically having trouble with the setCoefficient function of my code, where I need to resize a dynamic array if I am trying to at a term to my polynomial that is larger than what the array can currently hold.
I tried following some other stack overflow posts on how to resize a dynamic array, but keep running into errors. Currently, I am running into an error of HEAP CORRUPTION DETECTED when I try and delete the old dynamic array in the setCoefficient function.
I have commented the setCoefficient function and was hoping someone could go through and help me determine where I am going wrong. Unfortunately, I am not allowed to use the STL vector class for this assignment.
Here is my .cpp file where you can see the implementation of the setCoefficient function that I am having trouble with:
#include "poly.h"
//Default constructor. Initializes a Poly to: 0x^0
Poly::Poly()
{
cout << "No parameter constructor called" << endl;
polyArray = new int[1];
//polyArray[1] = 0;
polyArray[0] = 0;
length = 0;
}
//Constructor with one argument. Initialized to: coefficientx^0
Poly::Poly(int coefficient)
{
cout << "One parameter constructor called" << endl;
cout << "coefficient: " << coefficient << endl;
polyArray = new int[1];
//polyArray[1] = 0;
polyArray[0] = coefficient;
length = 0;
}
//Constructor with two arguments. Initialized to: coefficientx^power
Poly::Poly(int coefficient, int power)
{
cout << "Two parameter constructor called" << endl;
cout << "power: " << power << endl;
cout << "coeff: " << coefficient << endl;
polyArray = new int[power]; //I think I need to add 1 here to account for that fact that arrays start at index 0.
for (int i = 0; i < power; i++) { //I want to initialize the dynamic array to all 0's
polyArray[i] = 0;
}
polyArray[power] = coefficient;
length = power;
}
//Destructor
Poly::~Poly()
{
cout << "I am the destructor" << endl;
polyArray = NULL;
delete [] polyArray;
}
//Copy constructor. Creates a deep copy of a Poly.
Poly::Poly(const Poly& p)
{
cout << "Copy constructor" << endl;
this->length = p.length;
cout << "this->length: " << this->length << endl;
cout << "p.length: " << p.length << endl;
this->polyArray = new int[this->length];
//Loop throguh the initial Poly and assign all values in the array to the new Poly.
for (int i = 0; i<=p.length; i++) {
this->polyArray[i] = p.polyArray[i];
cout << "this polyArray: " << this->polyArray[i] << endl;
cout << "p.polyArray: " << p.polyArray[i] << endl;
}
}
void Poly::setCoefficient(const int coefficient, const int power) {
if (power > this->length) {
//we need to resize the array we currently have.
//Here I am creating a new array that will temporarily store larger values
int* resizedArray = new int[power * 2];
//This for loop assigns all the values in the current object's array to the new array (resizedArray)
for (int i = 0; i < this->length; i++) {
resizedArray[i] = this->polyArray[i];
}
//Here I am adding the term that we wanted to add in the first place with setCoefficient
resizedArray[power] = coefficient;
//Deleting the terms in polyArray
delete [] this->polyArray;
//Creating a new array that has been resized
this->polyArray = new int[power * 2];
//Setting the values of the temporary array, resizedArray, to the array of the current object.
this->polyArray = resizedArray;
//modifying the length of the current object.
this->length = power * 2;
}
else {
this->polyArray[power] = coefficient;
}
}
and for completeness, here is my .h file as well (although I dont think the issue is in my .h:
// ------------------------------------------------ Poly.h ----------------------------------------------
#ifndef Poly_H
#define Poly_H
#include <iostream>
#include <string>
using namespace std;
class Poly {
friend ostream& operator<<(ostream& out, const Poly& p);
friend istream& operator>>(istream& in, Poly& p);
public:
//Member functions
Poly(); //Default constructor. Initializes a Poly to: 0x^0
Poly(int coefficient); //Constructor with one argument. Initialized to: coefficientx^0
Poly(int coefficient, int power); //Constructor with two arguments. Initialized to: coefficientx^power
Poly(const Poly& p); //Copy constructor. Creates a deep copy of a Poly.
~Poly(); //Destructor
int degree() const; //Returns the largest degree term in a Poly.
double getCoefficient(const int power) const; //returns the coefficient of the x^power term.
//Poly setCoefficient(const int coefficient, const int power); //Sets the coefficient of the term indicated by the power.
void setCoefficient(const int coefficient, const int power);
// Arithmetic operators
Poly operator+(const Poly& p) const;
Poly operator-(const Poly& p) const;
// Boolean comparison operators
bool operator==(const Poly& p) const;
bool operator!=(const Poly& p) const;
// Assignment operators
Poly& operator=(const Poly& p);
Poly& operator+=(const Poly& p);
Poly& operator-=(const Poly& p);
Poly& operator*=(const Poly& p);
//Clean up/delete all Poly terms.
void clear();
//Checks if the Poly is empty or not.
bool isEmpty() const;
private:
int length; //# of terms in the Poly/size of the array
int* polyArray;
};
#endif
One error is here (cout statements removed for brevity):
this->length = p.length;
this->polyArray = new int[this->length];
for (int i = 0; i<=p.length; i++) {
this->polyArray[i] = p.polyArray[i];
}
The test in your for-loop should be i<p.length rather than i<=p.length. Otherwise you are writing one value past the end of polyArray, which invokes undefined behavior (which can result and often does in a crash)

C++ Function causing app to crash and not working properly

A problem has come up in my application where my PrintAll function will not work correctly and only ultimately crash my application. My app is supposed to read strings from a file and insert them into an array. The problem is it is reading incorrectly and will ultimately crash my app. Here is where I think the problem lies:
int main()
{
LoadMovies();
MovieList *movies = LoadMovies();
//movies->MovieList::PrintAll();
// // test methods for the Movie and MovieList classes
//PrintAllMoviesMadeInYear(movies, 1984);
//PrintAllMoviesWithStartLetter(movies, 'B');
//PrintAllTopNMovies(movies, 5);
//delete movies;
return 0;
}
MovieList* LoadMovies()
{
vector<string> movies;
ReadMovieFile(movies);
MovieList ml = MovieList(movies.size());
string name;
int year;
double rating;
int votes;
for (int i = 0; i < movies.size(); i++)
{
istringstream input_string(movies[i]);
getline(input_string, name, '\t');
input_string >> year >> rating >> votes;
Movie movie (name, year, votes, rating);
ml.Add(movie);
}
ml.PrintAll();
}
Complete Example:
/*
* File: MovieStatsProgram.cpp
* Author:
* Date:
* ===============================================================
* This is a console app to test the Movie and MovieList classes.
*
* TODO:
*
* You need to finish the implementation of the loadMovies method
* to create and initialize the MovieList object.
*
* You also need to create three static methods:
*
* PrintAllMoviesMadeInYear - it will print all the movies made in a
* given year once sort in alphabetical order and once sorted by the number
* of votes with the movie with the most number of votes printed first.
*
* PrintAllMoviesWithStartLetter - it will print all the movies started with
* a given letter sorted in alphabetical order
*
* PrintAllTopNMovies - it will display the top N movies based on the number of
* votes
*/
#include <iostream>
#include <sstream>
#include <vector>
#include <string>
#include <iomanip>
#include <fstream>
using namespace std;
class Movie {
public:
Movie();
Movie(string n, int y, int v, double r);
string get_name();
void set_name(string n);
int get_year();
void set_year(int y);
int get_votes();
void set_votes(int v);
double get_rating();
void set_rating(double r);
string PrintMovie();
private:
string name;
int year_made;
int votes;
double rating;
};
Movie::Movie() {
name = "null";
year_made = 0;
votes = 0;
rating = 0.0;
}
Movie::Movie(string n, int y, int v, double r) {
name = n;
year_made = y;
votes = v;
rating = r;
}
string Movie::get_name() {
return name;
}
void Movie::set_name(string n) {
name = n;
}
int Movie::get_year() {
return year_made;
}
void Movie::set_year(int y) {
year_made = y;
}
int Movie::get_votes() {
return votes;
}
void Movie::set_votes(int v) {
votes = v;
}
double Movie::get_rating() {
return rating;
}
void Movie::set_rating(double r) {
rating = r;
}
string Movie::PrintMovie() {
cout << fixed << setprecision(1) << rating << "\t\t" << votes << "\t\t" << "(" <<
year_made << ")" << "\t" << name << endl;
}
class MovieList {
public:
MovieList(int size);
~MovieList();
int Length();
bool IsFull();
void Add(Movie const& m);
string PrintAll();
private:
Movie* movies;
int last_movie_index;
int movies_size;
int movie_count = 0;
};
MovieList::MovieList(int size) {
movies_size = size;
movies = new Movie[movies_size];
last_movie_index = -1;
}
MovieList::~MovieList() {
delete [] movies;
}
int MovieList::Length() {
return last_movie_index;
}
bool MovieList::IsFull() {
return last_movie_index == movies_size;
}
void MovieList::Add(Movie const& m)
{
if (IsFull()) {
cout << "Cannot add movie, list is full" << endl;
return;
}
++last_movie_index;
movies[last_movie_index] = m;
}
string MovieList::PrintAll() {
for (int i = 0; i < last_movie_index; i++) {
movies[last_movie_index].Movie::PrintMovie();
//cout << movies[last_movie_index] << endl;
}
}
void ReadMovieFile(vector<string> &movies);
MovieList* LoadMovies();
enum MovieSortOrder
{
BY_YEAR = 0,
BY_NAME = 1,
BY_VOTES = 2
};
int main()
{
LoadMovies();
MovieList *movies = LoadMovies();
//movies->MovieList::PrintAll();
// // test methods for the Movie and MovieList classes
//PrintAllMoviesMadeInYear(movies, 1984);
//PrintAllMoviesWithStartLetter(movies, 'B');
//PrintAllTopNMovies(movies, 5);
//delete movies;
return 0;
}
MovieList* LoadMovies()
{
vector<string> movies;
ReadMovieFile(movies);
MovieList ml = MovieList(movies.size());
string name;
int year;
double rating;
int votes;
for (int i = 0; i < movies.size(); i++)
{
istringstream input_string(movies[i]);
getline(input_string, name, '\t');
input_string >> year >> rating >> votes;
Movie movie (name, year, votes, rating);
ml.Add(movie);
}
ml.PrintAll();
}
void ReadMovieFile(vector<string> &movies)
{
ifstream instream;
instream.open("imdbtop250.txt");
if (instream.fail())
{
cout << "Error opening imdbtop250.txt" << endl;
exit(1);
}
while (!instream.eof())
{
string movie;
getline(instream, movie);
movies.push_back(movie);
}
instream.close();
}
When I use MovieList::PrintAll in the main function, my function just crashes, and when I put it in the LoadMovies function, it will read and add data incorrectly before crashing. The size of the list is 251 and the application will just read the same data 251 times.
You have a two part problem:
1: As Brad S stated, your function returns nothing. This is a no-no.
MovieList* LoadMovies()
{
MovieList ml = MovieList(movies.size());
// Your function returns a pointer to a MovieList, so...
return &ml;
}
So, problem #2 is that you're going to return a pointer to something you created on the stack in your function. When you try to access it outside of your function, you'll run into undefined behavior.
Option 1:
MovieList* ml = new MovieList( movies.size() );
return ml;
You now need to delete ml when you're done w/ it.
Option 2:
Change your function to return a non-pointer... then you don't have the hassle of managing the memory.
EDIT: Try this
int main()
{
// Don't need this
// LoadMovies();
MovieList *movies = LoadMovies();
// Uncommented this
delete movies;
return 0;
}
MovieList* LoadMovies()
{
vector<string> movies;
ReadMovieFile(movies);
// CHANGE
MovieList* ml = new MovieList(movies.size());
// CHANGE
string name;
int year;
double rating;
int votes;
for (int i = 0; i < movies.size(); i++)
{
istringstream input_string(movies[i]);
getline(input_string, name, '\t');
input_string >> year >> rating >> votes;
Movie movie (name, year, votes, rating);
ml.Add(movie);
}
ml.PrintAll();
// CHANGE
return ml;
}
Your MovieList class has a fundamental problem. This comes to light on this line:
MovieList ml = MovieList(movies.size());
Your MovieList class has a member that is a pointer to dynamically allocated memory. Once you have this, you have to manage copying and assignment by creating a user-defined copy constructor and assignment operator.
The easiest fix for this is to use std::vector<Movie> instead of Movie * as a member variable of MovieList. Then copy-assignment comes for free and you don't need to implement further functions.
However, if you can't use std::vector for some reason, the following functions can be added:
class MovieList {
public:
//...
MovieList(const MovieList& m);
MovieList& operator=(MovieList m);
//...
};
#include <algorithm>
//...
// copy constructor
MovieList::MovieList(const MoveList& m) {
movies_size = m.size;
movie_count = m.movie.count;
last_movie_index = m.last_movie_index;
movies = new Movie[movies_size];
for (int i = 0; i < movies_size; ++i)
movies[i] = m.movies[i];
}
//...
// assignment operator
MovieList& MovieList::operator=(MoveList m) {
std::swap(m.movie_size, movie_size);
std::swap(m.last_movie_index, last_movie_index);
std::swap(m.movies, movies);
std::swap(m.movie_count, moviE_count);
return *this;
}
The easiest way to describe this to you is not to describe what these do. The best thing for you is to use your debugger and put a breakpoint in any of these functions and step through the code. When you hit the line I mentioned above, you will more than likely see that the copy constructor function is called -- then you can see it in action as to what it is doing.
The assignment operator is the function that's called when you assign an existing MovieList to another MovieList. It's implemented via the copy/swap idiom. This relies on a working copy constructor (provided above), and a destructor (which you already provided in your code). It works by creating a temporary MovieList, and swapping out the internals of the current MovieList with the temporary MovieList. There are many threads on SO as to how this works.
As to the reason why you need these functions above is that without the above functions, the line:
MovieList ml = MovieList(movies.size());
will create two MovieList objects, one temporary and one non-temporary, however the movies pointer for both will be pointing to the same memory. When the temporary is destroyed, the destructor is called, thus deleting the memory pointed to by movies. Now you have m1 pointing to memory that has gone up in smoke. Bad news when you try to use m1.
The user-defined copy and assignment functions above properly copy the object so that you get two distinct memory allocations for movies, so that when the destructor is called, the memory deleted will be unique to that object.
Again, all of this would be alleviated if you used std::vector and forego having to write copy ctor/assignment operators.

C++ MovieList array and pointer

I'm still a bit stuck on another part on my assignment.
Here is what the prompt is asking:
Now you can modify the LoadMovies function to create a MovieList
object and add each of the Movie objects to it. The function
LoadMovies should return a pointer to the MovieList object. That means
you need to create the MovieList object dynamically and on the heap.
Change the main function and store the returned MovieList pointer in a
variable. To test if everything works as expected, you can use the
PrintAll function of the MovieList object.
Here is my code so far:
class MovieList {
public:
Movie* movies;
int last_movie_index;
int movies_size;
int movie_count = 0;
MovieList(int size) {
movies_size = size;
movies = new Movie[movies_size];
last_movie_index = -1;
}
~MovieList() {
delete [] movies;
}
int Length() {
return movie_count;
}
bool IsFull() {
return movie_count == movies_size;
}
void Add(Movie const& m)
{
if (IsFull())
{
cout << "Cannot add movie, list is full" << endl;
return;
}
++last_movie_index;
movies[last_movie_index] = m;
}
void PrintAll() {
for (int i = 0; i < movie_count; i++) {
movies[last_movie_index].PrintMovie();
}
}
};
void ReadMovieFile(vector<string> &movies);
void LoadMovies();
enum MovieSortOrder
{
BY_YEAR = 0,
BY_NAME = 1,
BY_VOTES = 2
};
int main()
{
LoadMovies();
// TODO:
// You need to implement the Movie and MovieList classes and
// the methods below so that the program will produce
// the output described in the assignment.
//
// Once you have implemented everything, you should be able
// to simply uncomment the code below and run the program.
MovieList *movies = LoadMovies();
// // test methods for the Movie and MovieList classes
//PrintAllMoviesMadeInYear(movies, 1984);
//PrintAllMoviesWithStartLetter(movies, 'B');
//PrintAllTopNMovies(movies, 5);
//delete movies;
return 0;
}
void LoadMovies()
{
vector<string> movies;
ReadMovieFile(movies);
string name;
int year;
double rating;
int votes;
for (int i = 0; i < movies.size(); i++)
{
istringstream input_string(movies[i]);
getline(input_string, name, '\t');
input_string >> year >> rating >> votes;
Movie movie (name, year, votes, rating);
movie.PrintMovie();
}
}
Now where I'm stuck at is where the professor asks me to modify the LoadMovies in the prompt and turn it into a pointer. I'm drawing blanks. Also for some reason if I try to compile it says:
C:\Users\Andy\Documents\C++ Homework\MovieStatisticsProgram\MovieStatsProgram.cpp:163: error: void value not ignored as it ought to be
MovieList *movies = LoadMovies();
^
The order of your constructor is wrong
MovieList(int size) {
movies = new int[movies_size]; // movies_size hasn't been initialized yet!
movies_size = size;
last_movie_index = -1;
}
It should be
MovieList(int size)
: movies_size{size}, movies{new int[size]}, last_movie_index{0}
{}
Though as #ScottMcP-MVP noted your array should be
Movie* movie;
So your constuctor would be
MovieList(int size)
: movies_size{size}, movies{new Movie[size]}, last_movie_index{0}
{}
Some advice for getting started on the remaining functions
Length function will return how many are current used from last_movie_index.
IsFull will check if last_movie_index == movies_size - 1
Add will need to use last_movie_index to figure out what element in your array to store the movie.
PrintAll will have to iterate from [0] to [movie_count] and print out each element.
Your Add function would look something like
void MovieList::Add(Movie const& m)
{
if (IsFull())
{
std::cout << "Cannot add movie, list is full" << std::endl;
return;
}
movies[last_movie_index] = m; // assigns a copy to your array
++last_movie_index; // Increment the movie index
}

how do i create an array where each element in the array, of size 10, is pointing to an object, in C++?

for example lets have a class or struct name Employee with two constructors, a default constructor and a constructor with parameters two strings and an int. why doesn't the following code work?
Employee *employees = (employee*) malloc(sizeof(Employee)*10);
let's say we have an array, size 10, of type string for first name, last name, and one of type int for salary. how to initialize the data members of each object class using the constructor with the parameters?
for (int i = 0; i < 10; i++)
{
employees[i] = employee(firstname[i], lastname[i], salary[i]);
}
I've been trying to do this for a few days now but wasn't successful. Also, can anyone tell how to do this using c++'s new and delete operator? and also is there a way this can be done using vectors?
Thank you
header file
class employee{
std::string firstname;
std::string lastname;
int salary;
public:
employee(std::string, std::string , int);
employee();
void setFirst(std::string);
void setLast(std::string);
void setSalary(int);
std::string getFirst();
std::string getLast();
int getSalary();
};
employee::employee(std::string x, std::string y, int z)
{
setFirst(x);
setLast(y);
setSalary(z);
}
void employee::setFirst(std::string x)
{
firstname = x;
}
void employee::setLast(std::string y)
{
lastname = y;
}
void employee::setSalary(int z)
{
salary = z > 0 ? z : 0;
}
std::string employee::getFirst()
{
return firstname;
}
std::string employee::getLast()
{
return lastname;
}
int employee::getSalary()
{
return salary;
}
.cpp file
#define MAX 20
using namespace std;
int main(int argc, char* argv[])
{
int n = 1;
cout << "number of employees: ";
cin >> n;
string firstname[MAX];
string lastname[MAX];
double salary[MAX];
float raise[MAX];
for (int i = 0; i < n; i++)
{
cout << "Employee " << i + 1 <<endl;
cout << "-----------\n";
cout << "First Name: ";
cin >> firstname[i];
cout << "Last Name: ";
cin >> lastname[i];
cout << "Monthly Salary: ";
cin >> salary[i];
salary[i] *= 12;
cout <<"Yearly percentage raise (e.g 10% or 0%): ";
scanf("%f%%", &raise[i]);
salary[i] *= (((raise[i])/100.00) + 1);
puts("\n");
}
employee *employees = (employee*) malloc(sizeof(employee)*10);
for (int i = 0; i < n; i++)
{
employees[i] = employee(firstname[i], lastname[i], salary[i]);
}
cout << "TESING USING GET FUNCTIONS" << endl;
cout << "---------------------------\n\n";
for (int i = 0; i < n; i++)
{
cout << "Employee " <<i +1<< endl;
cout <<"-----------\n";
printf("First Name: %s", employees[i].getFirst().c_str());
printf("\nLast Name: %s",employees[i].getLast().c_str());
printf("\nYearly Salary: %d\n\n", employees[i].getSalary());
}
}
If you have an array of Employee instances and Employee is not POD (http://en.wikipedia.org/wiki/POD) you need to allocate memory from the stack using the operator new:
Employee* employees = new Employee[10];
And for having this working:
for (int i = 0; i < 10; i++)
{
employees[i] = Employee(firstname[i], lastname[i], age[i]);
}
you need to implement the operator= in your Employee class:
Employee& operator=(const Employee& src)
{
_firstname = src._firstname;
_lastname = src._lastname;
_age = src._age;
return *this;
}
If this looks like your Employee class:
class Employee
{
std::string first_name;
std::string last_name;
// other members and functions ...
};
Then using malloc() to create 10 of these is a complete and utter failure. The reason why is that yes, you allocated memory using malloc(), but that's all you did. You didn't construct 10 Employee objects. Those std::string members need to be constructed, not merely have memory allocated. So with that call to malloc() you have 10 fake Employees that were "created", and as soon as you attempt to do anything with one of them, then boom goes your program.
Do research on POD and non-POD types. You cannot treat non-POD types (as the class above is non-POD) as you would a POD type. For a non-POD type, the instance must be "officially" constructed, (the constructor must be invoked).
On the other hand, malloc() knows nothing concerning C++ and what is required to create an object correctly via construction. All malloc (and calloc, and realloc) knows is to allocate bytes and return a pointer to the allocated space.
Use a vector instead, it's resizable, it's easier to manage, and as Grady stated in his comment, it's also generally not good practice to use malloc in C++ code (although it's possible). Maybe do something that looks like this:
#include <vector>
...
int size = 10;
std::vector<Employee *> employees;
for(int i = 0; i < size; i++)
{
//as far as pulling in your data, that depends on where it's coming from
Employee *temp = new Employee(...);
employees.push_back(temp);
}
I'm rusty on my C++ but this should work.
Try this way:
#include <iostream>
class Employee
{
std::string m_firstname;
std::string m_lastname;
int m_age;
public:
Employee()
{
m_firstname=m_lastname="";
m_age=0;
}
void setFirstName(std::string firstname)
{
m_firstname=firstname;
}
void setLastName(std::string lastname)
{
m_lastname=lastname;
}
void setAge(int age)
{
m_age=age;
}
void displayEmp()
{
std::cout<<m_firstname;
std::cout<<m_lastname;
std::cout<<m_age;
}
};
int main()
{
std::string fname;
std::string lname;
int age;
Employee *employee = new Employee[10];
Employee *employeeptr=employee;
for(int i=0;i<10;i++)
{
std::cin>>fname;
std::cin>>lname;
std::cin>>age;
employeeptr->setFirstName(fname);
employeeptr->setLastName(lname);
employeeptr->setAge(age);
employeeptr++;
}
employeeptr=employee;
for(int i=0;i<10;i++)
{
employeeptr->displayEmp();
employeeptr++;
}
delete []employee;
return 0;
}

cannot swap objects in an array in C++

i am new to C++ and stuck in the swap stuff
the code below is a program of sort employee names in alphbetical order and print out the orginal one and sorted one ,but the
swap method doesn't work
the two output of printEmployees is excatly the same, can anyone help me? thx
#include <iostream>
#include <string>
#include <iomanip>
#include <algorithm>
using namespace std;
class employee
{
/* Employee class to contain employee data
*/
private:
string surname;
double hourlyRate;
int empNumber;
public:
employee() {
hourlyRate = -1;
empNumber = -1;
surname = "";
}
employee(const employee &other) :
surname(other.surname),
hourlyRate(other.hourlyRate),
empNumber(other.empNumber){}
void setEmployee(const string &name, double rate,int num);
string getSurname() const;
void printEmployee() const;
employee& operator = (const employee &other)
{employee temp(other);
return *this;}};
void employee::setEmployee(const string &name, double rate, int num) {
surname = name;
hourlyRate = rate;
empNumber = num;
}
string employee::getSurname() const { return surname; }
void employee::printEmployee() const {
cout << fixed;
cout << setw(20) << surname << setw(4) << empNumber << " " << hourlyRate << "\n";
}
void printEmployees(employee employees[], int number)
{
int i;
for (i=0; i<number; i++) { employees[i].printEmployee(); }
cout << "\n";
}
void swap(employee employees[], int a, int b)
{
employee temp(employees[a]);
employees[a] = employees[b];
employees[b] = temp;
}
void sortEmployees(employee employees[], int number)
{
/* use selection sort to order employees,
in employee
name order
*/
int inner, outer, max;
for (outer=number-1; outer>0; outer--)
{
// run though array number of times
max = 0;
for (inner=1;
inner<=outer; inner++)
{
// find alphabeticaly largest surname in section of array
if (employees
[inner].getSurname() < employees[max].getSurname())
max = inner;
}
if (max != outer)
{
//
swap largest with last element looked at in array
swap(employees, max, outer);
}
}
}
int main()
{
employee employees[5];
employees[0].setEmployee("Stone", 35.75, 053);
employees[1].setEmployee
("Rubble", 12, 163);
employees[2].setEmployee("Flintstone", 15.75, 97);
employees[3].setEmployee("Pebble", 10.25, 104);
employees[4].setEmployee("Rockwall", 22.75, 15);
printEmployees(employees, 5);
sortEmployees(employees,5);
printEmployees(employees, 5);
return 0;
}
This code is broken:
employee& operator = (const employee &other)
{employee temp(other);
return *this;}
It should be something like:
employee& operator= (const employee &other)
{
surname = other.surname;
hourlyRate = other.hourlyRate;
empNumber = other.empNumber;
return *this;
}
As told by others, fixing your assignment operator will solve the problem.
I see that you tried to implement operator= in terms of copy constructor but missed to do a swap. You can try the below approach if you want to avoid code duplication in your copy constructor and assignment operator.
employee& operator=(const employee& other)
{
employee temp(other);
swap(temp);
return *this;
}
void swap(employee& other)
{
std::swap(surname, other.surname);
std::swap(hourlyRate, other.hourlyRate);
std::swap(empNumber, other.empNumber);
}