Passing an array of pointers to a Class Object - c++

Hoping someone can help a beginner out here. I searched but some of the solutions were out of scope my knowledge. I'm trying to create a function which will take in a an array of pointers to a class object and output a getName() function for each object. But I keep getting a "no instance of overloaded function". I can't figure out what the problem is. Please take a look at following code.
#include <iostream>
#include "Student.hpp"
#include <string>
using namespace std;
void getName(Student *studentArray[], int); //prototype
int main()
{
//Creates class objects with Constructors Name and Score
//Class object has a function getName() to return name
Student stud1("John", 100);
Student stud2("Mary", 90);
Student stud3 ("Jack", 85);
//Create an array of student objects
Student myArray[3]= {stud1, stud2, stud3};
//ERROR HERE NO INSTANCE OF OVERLOADED FUNCTON
getName(myArray, 3)
return 0;
}
void getName(Student *studentsArray[], int arraySize)
{
for(int index=0; index < arraySize; index++)
{
cout << studentsArray[index]->getName() << endl;
}
}

Student *studentsArray[] is an array of pointers to students:
[-> "John", -> "Mary", -> "Jack"]
While Student *studentsArray is a pointer to a student (e.g. the first of an array):
-> [ "John", "Mary", "Jack" ]
using the [] operator you can jump to the offset relative to a pointer
studentsArray[0] == (*studentsArray)
studentsArray[1] == *(studentsArray+1)
studentsArray[2] == *(studentsArray+2)
and the -> operator is syntactic sugar for (*var).
The problem is that you created an array of students instead of an array of pointers of students:
Student myArray[3] = {stud1, stud2, stud3};
should actually be
Student* myArray[3] = { &stud1, &stud2, &stud3 };
Here is a full working example:
#include <iostream>
#include "Student.hpp"
#include <string>
using namespace std;
void getName(Student *studentsArray[], int); //prototype
int main()
{
//Creates class objects with Constructors Name and Score
//Class object has a function getName() to return name
Student stud1("John", 100);
Student stud2("Mary", 90);
Student stud3("Jack", 85);
//Create an array of student objects
Student* myArray[3] = { &stud1, &stud2, &stud3 };
getName(myArray, 3);
return 0;
}
void getName(Student *studentsArray[], int arraySize)
{
for (int index = 0; index < arraySize; index++)
{
cout << studentsArray[index]->getName() << endl;
}
}

The most important thing is that your pointer doesn't actually point any existing variable or its address. In this case, pointer will instead point a randomly chosen memory cell address, so it's really dangerous because you will never know what it will cause, including data lose, memory leak and so on.

With std::vector, it would be something like:
#include "Student.hpp"
#include <iostream>
#include <string>
#include <vector>
void displayNames(const std::vector<Student>& students);
int main()
{
Student stud1("John", 100);
Student stud2("Mary", 90);
Student stud3("Jack", 85);
std::vector<Student> students = {stud1, stud2, stud3};
displayNames(students);
return 0;
}
void displayNames(const std::vector<Student>& students)
{
for (const auto& student : students)
{
std::cout << student.getName() << std::endl;
}
}

Related

Code exiting when Dynamic Array of class allocated

I am trying to dynamically allocate an array and whenever it gets to the part where it dynamically allocates the program exits. I would rather not use vectors as I am trying to learn how to do this using dynamic arrays.
This is the simplified code:
#include <iostream>
#include <string>
using namespace std;
class Student
{
private:
double calcAverage(double* testArray);
char calcGrade(double average);
public:
int nTests, sameTests, idNum;
string name;
double average, *testArray;
char grade;
};
int i;
Student fillStudentArray(int nStudents);
int main()
{
*studentArray = fillStudentArray(nStudents);
return 0;
}
Student fillStudentArray(int nStudents)
{
Student *newStudentArray = new Student[nStudents];
cout << "If you can see this I worked. ";
delete[] studentArray;
return *newStudentArray;
}
I have tried the solution posted here Creation of Dynamic Array of Dynamic Objects in C++ but it also exits in a similar way. The main for the code looks like this.
int main()
{
int nStudents = 3; //this number is just for testing, in actual code it has user input
Student** studentArray = new Student*[nStudents];
cout << "1 ";
for(i = 0; i < nStudents; i++)
{
cout << "2 ";
studentArray[i] = new Student[25];
cout << "3 ";
}
return 0;
}
close (heres a cigar anyway)
Student* fillStudentArray(int nStudents); <<== function must return pointer to students
int main()
{
int nStudents = 3; <<<=== declared nstudents
Student *studentArray = fillStudentArray(nStudents); <<< declare studentArray
return 0;
}
Student *fillStudentArray(int nStudents) <<<== return pointer
{
Student* newStudentArray = new Student[nStudents];
cout << "If you can see this I worked. ";
// delete[] studentArray; <<<== what were you trying to delete?
return newStudentArray; <<<=== return pointer
}
the second code you showed is not relevant, its creating a 2d array

sort array of objects alphabetically c++

I am enrolled in an Object Oriented programming class and am using code::blocks as my IDE. We have a project that requires to pass an array of objects ( a Libray book array with private names and titles) into a sort array that will sort the titles or authors alphabetically. I have all the components working as they should be except the sort function. I used a sort function that I have used before in other programs but am having trouble getting it to work with this program. I am still in the beginning stages of learning how to code and would appreciate any feedback.
Header file:
#include <iostream>
#include <cstring>
using namespace std;
class Book
{
private:
string title;
string author;
public:
Book();
string getTitle();
string getAuthor();
void setTitle(string Title1);
void setAuthor(string Author1);
};
Main:
#include <iostream>
#include <cstring>
#include <iomanip>
#include "Library.h"
using namespace std;
//Sort function prototype
void s_sort (Book lib_books[], int n);
int main()
{
// Initializes n as the number of books
int n = 15;
//Declaration of array of objects
Book lib_books[15];
// Declartion of the private member "title" for each object
lib_books[0].setTitle("The Alchemist");
lib_books[1].setTitle("The Princess Bride");
lib_books[2].setTitle("The Catcher in the Rye");
lib_books[3].setTitle("1984");
lib_books[4].setTitle("Fahrenheit 451");
lib_books[5].setTitle("The Great Gatsby");
lib_books[6].setTitle("Poland");
lib_books[7].setTitle("The Cantebury Tales");
lib_books[8].setTitle("Leaves of Grass");
lib_books[9].setTitle("Where the Sidewalk Ends");
lib_books[10].setTitle("The Iliad");
lib_books[11].setTitle("Things to Think On");
lib_books[12].setTitle("The Grapes of Wraith");
lib_books[13].setTitle("Hop on Pop");
lib_books[14].setTitle("The Prince and the Pauper");
// Declartion of the private member "author" for each object
lib_books[0].setAuthor ("Paulo Coalho");
lib_books[1].setAuthor ("William Goldman");
lib_books[2].setAuthor ("J.D. Salinger");
lib_books[3].setAuthor ("George Orwell");
lib_books[4].setAuthor ("Ray Bradbury");
lib_books[5].setAuthor ("F. Scott Fitzgerald");
lib_books[6].setAuthor ("James A. Mitchener");
lib_books[7].setAuthor ("Chaucer");
lib_books[8].setAuthor ("Walt Whitman");
lib_books[9].setAuthor ("Shel Silverstein");
lib_books[10].setAuthor("Homer");
lib_books[11].setAuthor("Krishnamurti");
lib_books[12].setAuthor("John Steinbeck");
lib_books[13].setAuthor("Dr. Seuss");
lib_books[14].setAuthor("Mark Twain");
The portion of main that I'm having issues:
// Function to sort the books alphabetically by author
s_sort (lib_books,n);
cout << "\n";
// For loop to print all 15 books with author and title
for(int i = 0; i < 14; i++)
{
cout <<" "<<setw(25)<<lib_books[i].getTitle()<< " " <<lib_books[i].getTitle()<< "\n" ;
}
return 0;
}
//Sort function definition
void s_sort (Book::getTitle(), int n)
{
int m;
string hold;// Initializes 'hold' as a 'string' so all the characters will be used when it is sorted
for (int k=0; k<=n-1; k++)// 'For' loop sorts through the index
{
m = k;
for (int j=k+1; j <= n-1; j++)
{
if (lib_books[j].getTitle() < lib_books[m].getTitle());
//m = j;
}
// Swaps the lib_book[].getTitle() around and uses 'hold' as a placement
hold = lib_books[m].getTitle();
lib_books[m].getTitle() = lib_books[k].getTitle();
lib_books[k].getTitle() = hold;
hold = lib_books[m].getAuthor();
lib_books[m].getAuthor() = lib_books[k].getAuthor();
lib_books[k].getAuthor() = hold;
}
}
Implementation file:
#include <iostream>
#include <cstring>
#include "Library.h"
using namespace std;
Book::Book()
{
title = " ";
author = " ";
}
string Book::getTitle()
{
return title;
}
string Book::getAuthor()
{
return author;
}
void Book::setTitle(string Title1)
{
title= Title1;
}
void Book::setAuthor(string Author1)
{
author= Author1;
}
The problem that I am having is that it doesn't sort the array. It prints out the same list that was defined. I have tried to pass the array by reference but it needs a index number in the function prototype and definition.

C++ Object doesn't save value

Objects I created for the Player class does not change the private variable even tho it does in the function that changes it. There maybe some reference problems with the objects being used in the main() function but I can't figure out where or why.
Specifically the loop at the end of the main file prints the games won by the players in the vector Players but all the scores return 0. While when the player object.matchWon() function correctly parse and print the score and shows the change made to the private variable.
I suspect there are problems with the usage of getPlayer() function in the main code.
Thanks in advance!!
Player.cpp:
#include "Player.h"
#include <stdlib.h>
#include <iostream>
using namespace std;
//constructor
Player::Player(string first, string last) {
Player::first = first;
Player::last = last;
gWins = 0;
gLoss = 0;
mWins = 10;
mLoss = 2;
}
//setters
void Player::addLoss(int increment) {
this->gLoss+=increment;
}
void Player::addWins(int increment) {
this->gWins+=increment;
}
void Player::matchWon(vector<string> scores) {
for (int i = 5;i<scores.size()-1;i++){
cout<<(int)scores[i][0]-'0'<<"-";
cout<<(int)scores[i][2]-'0'<<endl;
gWins+=scores[i][0]-'0'; //add games won
cout<<gWins<<endl;
gLoss+=(int)scores[i][2]-'0'; //add games lost
}
this->mWins++;
}
void Player::matchLost(vector<string> scores) {
this->mLoss++;
}
double Player::winPercentage() {
return (double)mWins / mLoss;
}
//accessors
string Player::getFirstname() {
return this->first;
}
string Player::getLastname() {
return this->last;
}
int Player::getGameswon() {
//cout<<gWins;
return this->gWins;
}
main.cpp:
#include <iostream>
#include "player.h"
#include <fstream>
#include <vector>
#include <sstream>
using namespace std;
vector<string> split(const string &s) {
vector<string> elems;
istringstream iss(s);
do
{
string sub;
iss >> sub;
elems.push_back(sub);
//cout << "Substring: " << sub << endl;
} while (iss);
return elems;
}
Player &getPlayer(vector<Player> &players, const string &first, const string &last){
for (int i=0;i<players.size();i++){
if (players[i].getFirstname()==first&&players[i].getLastname()==last){
return players[i];
}
}
players.push_back(Player(first,last));
return (players[players.size()-1]);
}
int main(int argc, char *argv[]) {
ifstream file(argv[1]);
ofstream ofile(argv[2]);
if (!file.is_open()){
cerr <<"Could not open file\n";
return 0;
}
string line;
vector<Player> players;
while (getline(file,line).good()){
vector<string> lineParsed = split(line);
vector<string> matchData = split(line);
Player p1 = getPlayer(players,lineParsed[0],lineParsed[1]);
Player p2 = getPlayer(players,lineParsed[3],lineParsed[4]);
p1.matchWon(lineParsed);
cout<<p1.getFirstname()<<"!"<<p1.getGameswon()<<endl;
}
for (int i=0;i<players.size();i++){
//cout<<players.size();
cout<<players[i].getFirstname()<<":"<<players[i].getGameswon()<<endl;
}
return 0;
}
You're copying your players:
Player p1 = getPlayer(players,lineParsed[0],lineParsed[1]);
Player p2 = getPlayer(players,lineParsed[3],lineParsed[4]);
so when you p1.matchWon(), it happens to the local Player object, not the one in the vector.
Although the return type of getplayer() is Player&, that doesn't matter if you're assigning it to a non-reference variable. If you want to be modifying the Player instances in the vector, you should have
Player& p1 = getPlayer(players,lineParsed[0],lineParsed[1]);
Player& p2 = getPlayer(players,lineParsed[3],lineParsed[4]);
By the way, getPlayer() is unsafe. The vector might resize itself when you push_back to it, invalidating references. You may want to store a vector of pointers instead (or just make sure through e.g. resize() that the vector definitely has room for all the players you want to push to it).
It would help if you included the class definition. There seems to be something strange going on:
Player::first = first;
Player::last = last;
Are these static fields? If they are, the issue is that you only store the first and last (names?) of the last player you create.

c++ segmentation fault for dynamic arrays

I want to add a theater object into a boxoffice object in a C++ code. When I try to add it in main code, first one is added successfully. But a segmentation fault occurs for second and obvioulsy other theater objects. Here is the add function;
#include <iostream>
#include <string>
#include "BoxOffice.h"
using namespace std;
BoxOffice::BoxOffice()
{
sizeReserv = 0;
sizeTheater = 0;
theaters = new Theater[sizeTheater];
reserv = new Reservation[sizeReserv];
}
BoxOffice::~BoxOffice(){}
void BoxOffice::addTheater(int theaterId, string movieName, int numRows, int numSeatsPerRow){
bool theaterExist = false;
for(int i=0; i<sizeTheater; i++)
{
if(theaters[i].id == theaterId)
{
theaterExist=true;
}
}
if(theaterExist)
cout<<"Theater "<<theaterId<<"("<<movieName<<") already exists"<< endl;
else
{
++sizeTheater;
Theater *tempTheater = new Theater[sizeTheater];
if((sizeTheater > 1)){
tempTheater = theaters;
}
tempTheater[sizeTheater-1] = Theater(theaterId,movieName,numRows,numSeatsPerRow);
delete[] theaters;
theaters = tempTheater;
cout<<"Theater "<<theaterId<<"("<<movieName<<") has been added"<< endl;
cout<<endl;
delete[] tempTheater;
}
}
And I get segmentation fault on this line;
tempTheater[sizeTheater-1] = Theater(theaterId,movieName,numRows,numSeatsPerRow);
This is Theater cpp;
#include "Theater.h"
using namespace std;
Theater::Theater(){
id=0;
movieName="";
numRows=0;
numSeatsPerRow=0;
}
Theater::Theater(int TheaterId, string TheaterMovieName, int TheaterNumOfRows, int TheaterNumSeatsPerRow)
{
id = TheaterId;
movieName = TheaterMovieName;
numRows = TheaterNumOfRows;
numSeatsPerRow = TheaterNumSeatsPerRow;
theaterArray = new int*[TheaterNumOfRows];
for(int i=0;i<TheaterNumOfRows;i++)
theaterArray[i]= new int[TheaterNumSeatsPerRow];
for(int i=0; i<TheaterNumOfRows;i++){
for(int j=0;j<TheaterNumSeatsPerRow;j++){
theaterArray[i][j]=0;
}
}
}
This is header file of Theater;
#include <iostream>
#include <string>
using namespace std;
class Theater{
public:
int id;
string movieName;
int numRows;
int numSeatsPerRow;
int **theaterArray;
Theater();
Theater(int TheaterId, string TheaterMovieName, int TheaterNumOfRows, int TheaterNumSeatsPerRow);
};
And this is how i call add functions;
BoxOffice R;
R.addTheater(10425, "Ted", 4, 3);
R.addTheater(8234, "Cloud Atlas", 8, 3);
R.addTheater(9176, "Hope Springs",6,2);
The problematic lines are these:
if((sizeTheater > 1)){
tempTheater = theaters;
}
First you allocate memory and assign it to tempTheater, but here you overwrite that pointer so it will point to the old memory. It does not copy the memory. Since the code is for a homework assignment, I'll leave it up to you how to copy the data, but I do hope you follow the rule of three for the Theater class (as for the BoxOffice class) which will make it very simple.
Also, there's no need to allocate a zero-size "array", just make the pointers be nullptr (or 0).

C++ "No matching constructor for initializing Employee"

I am new to C++ and practicing using vector as an object. However, I got an error "No matching constructor for initializing Employee" when I tried running the following program.
Please tell me how I could modify my program!
Also, when I write
staff[0] = Employee{"Harry Potter" 55000};
does this mean that I am storing string and double data in one of 10 open boxes in vector object of type Employee?
I apologize for such a basic question.
Thank you so much in advance!!
#include<iostream>
#include<string>
#include<vector>
using namespace std;
class Employee
{
public:
Employee(string, double);
double get_salaries();
string get_name();
void set_salaries(double);
private:
string name;
double salaries;
};
Employee::Employee(string n, double s)
{
name = n;
salaries = s;
}
double Employee::get_salaries()
{
return salaries;
}
string Employee::get_name()
{
return name;
}
void Employee::set_salaries(double s)
{
salaries = s;
}
int main()
{
// using vector as an object
int i;
vector<Employee> staff(10);
staff[0] = Employee{"Harry Potter", 55000};
if (staff[i].get_salaries() < 100000)
cout << staff[i].get_salaries();
return 0;
}
Your Employee class does not have a default, parameterless, constructor.
When you create the staff vector, it will create 10 Employee objects, thus invoking the default constructor.
To support this,
vector<Employee> staff(10);
you have to provide default constructor in your class.
Your main method
int main()
{
// using vector as an object
int i; // [i] not initialized anywhere.
vector<Employee> staff(10); // Incorrect way of declaring a vector
staff[0] = Employee{"Harry Potter", 55000}; // Incorrect way of creating a instance of class
if (staff[i].get_salaries() < 100000)
cout << staff[i].get_salaries();
return 0;
}
Change your main method like this
int main()
{
vector<Employee> staff;
staff.push_back(Employee("Harry Potter", 55000));
if (staff[0].get_salaries() < 100000)
cout << staff[0].get_salaries();
return 0;
}