Copying vector and remaining the memory adress of the members - c++

I try to read in some data of teams and players and change the data.
The Player class members have pointers to the teams from the Team class, while the Teams have a playerlist filled with pointers to the players.
The problem comes with the readin()-function which reads in the team and player data from a txt.file and returns a vector of teams. After the readin-process the pointers created in the readin-process seem to direct to wrong addresses.
So reading out data from the vector of teams returned by the read-in function is not the same anymore than reading out the data from the pointers created in the read-in function.
Here is the general structur of the classes:
#include <iostream>
#include <vector>
#include <string>
class Player;
class Team
{
public:
std::vector<Player*> getplayerlist(){
return playerlist;
}
void setteamname(std::string x){
teamname = x;
}
std::string getteamname(){
return teamname;
}
void Team::addPlayer(Player* x){
playerlist.emplace_back(x);
};
private:
std::vector<Player*> playerlist;
std::string teamname;
};
class Player
{
public:
Team* getpteam(){
return pteam;
}
void setpteam(Team* x){
pteam = x;
}
void setinformation(std::string x, int y){
name= x;
id = y;
}
private:
int id;
std::string name;
Team* pteam;
};
And here is the structure of the read-in function
vector<Team> readin(){
//some readin stuff
//if the line contains the teamname
Team team;
team.setteamID_(a);
team.setteamname_(word2);
Teamvector.emplace_back(team);
//if the line contains player data
//add the player to the team created before
Player* player = new Player();
player->setinformation_(b, word1, lname, str, &Teamvector[a-1]);
Teamvector[a-1].addPlayer(player);
return Teamvector;
}
But if i compare the addresses of &Teamvektor[0] and
vector <Team> team = readin();
&team[0]
they are different. How can i "remain" the adress of the stored teams ?

You are returning std::vector by value: this means container is being copied, thus elements have same values but different addresses in memory.
There are few ways how to handle this. For example:
Create container and fill it in your method:
std::vector<Team> v;
void readin_fillVector( vector<Team>& v) {
//.. v.push_back( team);
}
Pass iterator
void readin_fillVector( std::back_insert_iterator< std::vector<Team> > it) {
//.. (*it)++ = team;
}

Related

C++ Creating Array of Objects

I'm having an issue with making one array with 3 objects. I'm trying to display the information of employees and my issue is that I don't know where I would assign the strings to the appropriate members and how to keep one variable for name. My code and an example are below:
class employee
{
private:
string name;
string idNumber;
public:
void setName(string);
void setIDnumber(string);
string getName();
string getIDnumber();
};
const int numEmployees = 3;
int main()
{
employee employeeInfo [numEmployees];
}
I want to create a constructor for 3 employees and input(name, idNumber). for example, in employeeInfo[0], the first employee, I want to input "Tom Jones", "123456"
and in employee[1], the second employee, "James Blyth", "QE123"
You can simply call the setter methods on the individual employee objects, eg:
int main()
{
employee employeeInfo [numEmployees];
employeeInfo[0].setName("Tom Jones");
employeeInfo[0].setIDNumber("123456");
employeeInfo[1].setName("James Blyth");
employeeInfo[1].setIDNumber("QE123");
// and so on...
...
}
If you really want to add a constructor, then it would look like this:
class employee
{
private:
string name;
string idNumber;
public:
employee() = default;
employee(string name, string idNumber);
...
};
employee::employee(string name, string idNumber) {
setName(name);
setIDnumber(idNumber);
};
...
int main()
{
employee employeeInfo [numEmployees];
employeeInfo[0] = employee("Tom Jones", "123456");
employeeInfo[1] = employee("James Blyth", "QE123");
// and so on...
}
Just note that this will default-construct the array elements first, and then construct temporary objects to overwrite the array elements.
If you want to avoid the temporaries, but still want a fixed array of objects stored consecutively, you can use placement-new to construct the array members directly using your non-default constructor, eg:
#include <type_traits>
int main()
{
std::aligned_storage_t<sizeof(employee), alignas(employee)> buffer[numEmployees];
employee* employeeInfo = reinterpret_cast<employee*>(buffer);
new(&employeeInfo[0]) employee("Tom Jones", "123456");
new(&employeeInfo[1]) employee("James Blyth", "QE123");
// and so on...
...
for(int i = 0; i < numEmployees; ++i) {
employeeInfo[i].~employee();
}
}
Or, you can use a std::vector (if you don't mind the array being allocated in dynamic memory), eg:
#include <vector>
int main()
{
std::vector<employee> employeeInfo;
employeeInfo.reserve(numEmployees);
employeeInfo.emplace("Tom Jones", "123456");
employeeInfo.emplace("James Blyth", "QE123");
// and so on...
...
}
Otherwise, create an array of pointers to objects instead, and then you can create the individual objects dynamically using new with your non-default constructor. The objects just won't be stored consecutively in memory, eg:
int main()
{
employee* employeeInfo[numEmployees];
employeeInfo[0] = new employee("Tom Jones", "123456");
employeeInfo[1] = new employee("James Blyth", "QE123");
// and so on...
...
for(int i = 0; i < numEmployees; ++i) {
delete employeeInfo[i];
}
}
Which would be safer handled with std::unique_ptr, eg:
#include <memory>
int main()
{
std::unique_ptr<employee> employeeInfo[numEmployees];
employeeInfo[0] = std::make_unique<employee>("Tom Jones", "123456");
employeeInfo[1] = std::make_unique<employee>("James Blyth", "QE123");
// and so on...
...
}

How can i link the vector elements to a pointer

I need help in the class design workflow with the following functionality.
I have a class with the name of Stage the stage has a variable of class Director as vector and i would want to point to these data elements of the vector from another class Channel.
class Stage
{
private:
int time;
std::vector<Director> directors;
public:
Stage()
{ }
void AddDirector(Director director)
{
directors.push_back(director);
}
Director* GetDirector(int index)
{
return &directors[index];
}
void DeleteDirector(std::string dirName)
{
// remove the director from the vector which matches the name of the input string
}
};
////////////////////////////////////////////////////////////////////////////////////////////////
class Director
{
private:
int time;
std::string stdstrDirName;
public:
Director()
{ }
std::string GetName()
{
return stdstrDirName;
}
void SetName(std::string name)
{
stdstrDirName = name;
}
// GetTime and SetTime
};
class Channel
{
private:
int time;
std::string stdstrChannelName;
Director* dir;
public:
Channel()
{ }
std::string GetName()
{
return stdstrChannelName;
}
void SetName(std::string name)
{
stdstrChannelName = name;
}
std::string GetDirectorName()
{
dir->GetName();
}
void SetDirector(Director* director)
{
dir = director;
}
};
This is how i would point them.
int main()
{
Stage stage; // Create Stage Object
Director d1, d2, d3; // Create Director Objects
Channel channel;
d1.SetName("D1"); d2.SetName("D2"); d3.SetName("D3");
stage.AddDirector(d1); stage.AddDirector(d2); stage.AddDirector(d3);
channel.SetDirector(stage.GetDirector(1)); // Link Director to Channel
}
This approach has a drawback whenever the vector gets resize the pointers in the Channel will not hold reference to their valid object.
I need help in what should be the design of the class structure ?
Perhaps your vector could store pointers to the Director objects rather than the objects themselves. That way, resizes will not affect existing pointers.
Have you thought of using reference(&) instead of pointers?

C++ Container and Entity Classes

I'm new to the site (and to programming) so I hope I post this question appropriately and under all the proper guidelines of the site. Ok, here it goes:
So I pretty new to C++ and am trying to create classes for a program. I have to construct "container and entity classes", but where I'm struggling is trying to nail down the proper syntax for my getter and setter functions in the container class. So here's the code I have so far:
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <string>
using namespace std;
const int MAX_STUDENTS=100;
const int MAX_COURSES=25;
const int NAME_SIZE=30;
const int COURSE_COLUMNS=4;
const int GRADE_ROWS=10;
//Entity Classes
class Course
{
//Two private member variables
private:
string courseText;
int courseID;
public:
//Constructor
Course(void)
{
//Just providing initial value to the two object variables
courseText;
courseID=-1;
}
//Setters and Getters for each variable
string getCourseText(){
return courseText;}
void setCourseText(string userEnteredText){
courseText = userEnteredText;}
int getCourseID(){
return courseID;}
void setCourseID(int userEnteredID){
courseID = userEnteredID;}
};
class Student
{
//Private member variables
private:
string studentText;
int studentID;
int** coursesAndGrades;
int enrolledCoursesCount;
int timesReallocatedColumns;
int timesReallocatedRows;
public:
//Constructor
Student(void)
{
//Just providing initial value to the object variables
studentText;
studentID=-1;
coursesAndGrades = new int*[GRADE_ROWS+1];
for(int i=0;i<(GRADE_ROWS+1);i++)
{
coursesAndGrades[i] = new int[COURSE_COLUMNS];
}
enrolledCoursesCount=0;
timesReallocatedColumns=0;
timesReallocatedRows=0;
}
//Setters and Getters for each variable
string getStudentText(){
return studentText;}
void setStudentText(string userEnteredText){
studentText = userEnteredText;}
int getStudentID(){
return studentID;}
void setCourseID(int userEnteredID){
studentID = userEnteredID;}
int getCoursesAndGrades(int gradeRow, int courseColumn){
return coursesAndGrades[gradeRow][courseColumn];}
void setCoursesAndGrades(int gradeRow, int courseColumn, int entry){
coursesAndGrades[gradeRow][courseColumn]=entry;}
int getEnrolledCoursesCount(){
return enrolledCoursesCount;}
void setEnrolledCoursesCount(int enrolledCount){
enrolledCoursesCount = enrolledCount;}
int getTimesReallocatedColumns(){
return timesReallocatedColumns;}
void setTimesReallocatedColumns(int reallocColumnCount){
timesReallocatedColumns = reallocColumnCount;}
int getTimesReallocatedRows(){
return timesReallocatedRows;}
void setTimesReallocatedRows(int reallocRowCount){
timesReallocatedRows = reallocRowCount;}
};
Now, I've got a container class called GradeBook which contains dynamically allocated arrays of these two entity class objects.
class GradeBook
{
private:
Course* courses;
Student* students;
public:
//Constructor
GradeBook(void)
{
courses = new Course [MAX_COURSES];
students = new Student [MAX_STUDENTS];
}
}
I'm trying to figure out the proper way to translate the setter and getter functions from my entity classes to the container class so I can change individual elements of each class object in the dynamically allocated array. These changes will happen in more public member functions in the container class, but I'm completely stumped. I hope this question makes sense, and I'm not looking for anyone to write all of the setters and getters for me, I just need someone to point me in the proper direction for the syntax. Thanks everyone who made it through this!
If you will have something like this:
class GradeBook
{
public:
...
Student& student(int idx) { /*some boundary check here*/
return students[idx]; }
}
then you can use that method as:
GradeBook theBook;
...
auto idOfFirstStudent = theBook.student(0).getStudentID();
You just need to decide what that student() method shall return: it can return reference (as above) or pointer to student (instance). In later case you can return nullptr in case of out-of-bound errors. In first case the only reasonable option is to throw an error.
So there's no magic needed here, but you do need to decide how you want to do it. One way would be to just write something like:
void GradeBook::setCourseText(int i, const string &txt) {
courses[i].setCourseText(txt);
}
BTW, I would highly recommend using std::vector and at() rather than new.

Classes accessing each other with pointers

I'm still confused with pointers, maybe you could enlighten me a bit.
I'm having some classes pointing to each other and don't get the way to access them in the right way.
#include <vector>
#include <iostream>
class Player;
class Trainer;
class Team {
Trainer* trainer_;
std::vector<Player*> player_;
public:
std::vector<Player*> player() { return player_; }
Trainer* trainer() { return trainer_; }
std::vector<Player*> get_playerlist(){
return player_;
};
};
class Player {
public:
void setteam_(Team* x){
team_ = x;
}
private:
Team* team_;
};
class Trainer {
Team* Team_;
};
int main()
{
Player player1;
Team team1;
std::vector<Player*> playerlist;
player1.setteam_(&team1);
playerlist = team1.get_playerlist();
std::cout << playerlist.size();
std::cin.get();
return 0;
}
In the main there is player1 created and assigned to the playerlist of team1, now he should somehow appear there when i get the playerlist. But the output of this code is that the size of the playerlist of team 1 is still 0. What did I do wrong ?
Your Team class has no method that actually adds players to the player_ vector. Setting the team_ pointer to the team1 instance is not sufficient.
player1.setteam_(&team1);
What happens next is:
void setteam_(Team* x){
team_ = x;
}
Here you are stating that this Player has pointer to Team set to the same address as x. But this doesn't mean that this Team object has pointer to player in std::vector. This doesn't happen automaticly, you need something like:
void setteam_(Team* x){
team_ = x;
x->addPlayer( this); // add to vector
}

How can I create multiple items with one class in C++?

I have the class Furniture with:
Furniture.h:
#include <iostream>
#include <string>
using namespace std;
class Furniture {
public:
Furniture();
~Furniture();
void setname(string name);
void setprice(double price);
double getprice();
string getname();
virtual void printSpecs();
private:
string name;
double price;
protected:
static int NumberOfItems;
int Id;
};
furniture.cpp:
#include "furniture.h"
Furniture::Furniture() {
}
Furniture::~Furniture() {
}
void Furniture::setname(string name) {
this->name = name;
}
string Furniture::getname()
{
return this->name;
}
void Furniture::setprice(double price) {
this->price = price;
}
double Furniture::getprice() {
return this->price;
}
void Furniture::printSpecs() {
cout<<"Price: "<<this->price<<endl;
cout<<"Name: "<<this->name<<endl;
}
int main() {
Furniture *model = new Furniture();
model->setname("FinalDestiny");
model->setprice(149.99);
model->printSpecs();
delete model;
}
Everything works fine but I want to add multiple furniture items with the same class and just update the NumberOfItems. Is there any way to do that?
Also, is my code ok? I mean, how can I improve it? I'm quite new to OOP and I'd like to learn some good practices.
Thanks.
The idea is conceptually broken. You cannot do that; you really need different objects.
Alternatively, if you really want to have multiple identical items, you can create one item and create multiple pointers to it, and maintain a separate count for the number of active items. A shared_ptr does that for instance.
That said, your code shouldn’t use pointers at all, this is a common anti-pattern in C++ code. Furthermore, your code probably shouldn’t have setters, provide a proper constructor instead:
int main() {
Furniture model("FinalDestiny", 149.99);
model.printSpecs();
}
Much shorter, simpler, and no possiblity of leaking memory.
To keep track of the number of items, you can update the number of items in the constructor:
Furniture::Furniture() {
Id = NumberOfItems++;
}
and decrement in the destructor if you want:
Furniture::~Furniture() {
NumberOfItems--;
}
To access the item by Id, you need to have an extra manager class or use a map:
std::map<int,Furniture*> items;
which you can pass as parameter to the constructor and update it there:
Furniture::Furniture(std::map& items) {
Id = NumberOfItems++;
items[Id] = this;
}
And, outside, you can simply retrieve items with:
Furniture* f = items[3];
I would write in this way
#include <iostream>
#include <string>
using namespace std;
class Furniture {
public:
Furniture(string name = "", double price = 0)
: name(name), price(price), Id(NumberOfItems++)
{}
Furniture(const Furniture &f)
: name(f.getname()), price(f.getprice()), Id(NumberOfItems++)
{}
void setname(string name) { this->name = name; }
void setprice(double price) { this->price = price; }
double getprice() const { return price; }
string getname() const { return name; }
virtual void printSpecs() {}
private:
string name;
double price;
protected:
static int NumberOfItems;
int Id;
};
int Furniture::NumberOfItems;
int main_furniture(int, char **)
{
Furniture a("product 1", 100);
Furniture x(a), y(a), z(a);
}
I've inlined just to simplify. What's interesting to you should be the copy constructor implementation, and (OT) you forget the const on getter...
Just increment NumberOfItems in the constructor, and decrement it in the destructor.
Store the furniture instances in an array or better in a vector. You can access them with an index or iterator. The NumberOfItems field doesn't belong in the furniture class, an instance of furniture shouldn't know about how many furniture items there are in the system. Use the size () method from vector to get the furniture item count.