C++ Insert into List of Objects - c++

can someone tell me how can i add data into my list of class with C++
please ?
#include <string>
class Person
{
private:
std::string Name;
public:
Person();
~Person();
std::string GetName()
{
return Name;
}
std::string SetName(std::string name)
{
name = Name;
return name;
}
};
void main()
{
list<Person> lp = new list<Person>();
Person p = new Person();
p.Name = "Smith";
lp.insert(p);
}
this is my attempt. Can someone correct me or give me another answer ? Thanks

If by some chance you are using c++11 or greater, consider using:
list.emplace_back()
or
list.emplace_front()
which handles construction and insertion. Of course this would be even better if you had a Person constructor that took a string argument.
Person::Person(std::string& name) { Name = name; }
In which case you could do:
lp.emplace_back("Smith");

list.insert() takes an iterator, i.e. position at which you want to insert the new element.
You can also do
list.push_back(p);
This inserts 'p' at the end of the list.
If you do
list.push_front(p);
insertion happens at the head of list.

First of all, since you're coding in c++ your main function should return an int:
int main()
Second, you're using the new keyword on an object that isn't a pointer, correct that:
// This would perhaps be better:
list<Person*> lp;
Person *p = new Person; // remember to delete p; later
I don't see that you have included <list> header and using std. You need that in order to use list. Or at least write std::list or using std::list;
You are trying to assign to a private class member, either declare it public, or use a setter function:
p->Name = "Smith"; // remember for pointers, use the '->' or *(p).Name
emplace_back() is maybe what you are looking to use (since c++11):
lp.emplace_back(p);
// otherwise, specify an iterator as first argument for insert:
// lp.insert(lp.end(), p);

Why isn't your SetName only void and needs to return something? If you want to return the new Name, you also should have
Name = name;
return Name;
You have switched it.
Also, you don't need any of the new and every main function should return int value (usually 0 if no error occurred).
FIXED CODE:
#include <string>
#include <list>
class Person
{
private:
std::string Name;
public:
//Person();
//~Person();
std::string GetName()
{
return Name;
}
void SetName(std::string name)
{
Name = name;
}
};
int main()
{
std::list<Person> lp;
Person p;
p.SetName("Smith");
lp.push_back(p);
return 0;
}
You need to include lists in order to use them, and you can't assign a private member directly. Also, your declarations are wrong - for this I would recommend some cpp tutorials and reading the documentation.

Related

Object going out of scope and destructor called causing the pointer following that object's address to have unreadable memory on each attribute

So I have a vector of pointers to Movie objects in a class called Movies and the Movies class has a member method add() which you pass in the following arguments: std::string name, std::string rating, size_t watched_times. Then that add() method constructs a Movie object with all the arguments passed in, then I push_back() the address of that Movie object, the problem is when the code block is finished that Movie object will be destructed and so all the attributes will be "unreadable memory" or "random".
I just can't figure out how to go around this, any ideas on how to try going about this would be greatly appreciated.
Movie.h:
#pragma once
#include <string>
class Movie {
private:
std::string name;
std::string rating;
size_t times_watched;
bool init{false};
public:
// private attribute getters
std::string return_name();
std::string return_rating();
size_t return_times_watched();
bool return_init();
// Methods
void increment();
Movie(std::string name_val, std::string rating_val, size_t times_watched_val); // Constructor
};
Movie.cpp:
#include "Movie.h"
// private attribute getters
std::string Movie::return_name() {
return name;
}
std::string Movie::return_rating() {
return rating;
}
size_t Movie::return_times_watched() {
return times_watched;
}
bool Movie::return_init() {
return init;
}
// Methods
void Movie::increment() {
++times_watched;
}
Movie::Movie(std::string name_val, std::string rating_val, size_t times_watched_val) : name{name_val}, rating{rating_val}, times_watched{times_watched_val}, init{true} {}
Movies.h:
#include "Movie.h"
#include <iostream>
#include <vector>
class Movies {
private:
std::vector<Movie*> movies;
public:
bool add(std::string name, std::string rating, size_t times_watched);
bool increment(std::string name);
void display();
};
Movies.cpp:
#include "Movies.h"
bool Movies::add(std::string name, std::string rating, size_t times_watched) {
for (size_t i{}; i < movies.size(); ++i) {
if (movies.at(i)->return_init() && movies.at(i)->return_name() == name) {
return false;
}
}
Movie to_add{name, rating, times_watched};
movies.push_back(&to_add); // Causing bug
return true; // End of loop means no name matching name was found to the new movie being added
}
As has been said in the comments, the issue is with
Movie to_add{name, rating, times_watched};
movies.push_back(&to_add);
After these lines, the Movie object goes out of scope, causing the to_add variable to be destroyed. The pointer you pushed onto the movies variable is no longer valid. Using it is then undefined behaviour.
There are a few possibilities to fix this. If you insist on storing points in the vector, then you can do
Movie *to_add = new Movie{name, rating, times_watched};
movies.push_back(to_add);
Since this object is now dynamically allocated, it will not be automatically destroyed. You will be responsible for freeing the memory though, presumably in the destructor of the Movies class. A better solution would be to change the vector to store Movie objects, as opposed to pointers, i.e. std::vector<Movie>. Then, you can simply push objects onto the vector.
Movie to_add{name, rating, times_watched};
movies.push_back(to_add);
or
movies.push_back(Movie{name, rating, times_watched});
As an aside, when passing objects into function, it's generally a good idea to pass them by constant reference, in order to prevent copies being made. Example:
bool Movies::add(std::string name, std::string rating, size_t times_watched)
Would become
bool Movies::add(const std::string &name, const std::string &rating, size_t times_watched)

function that create shared_ptr then add it to class member vector and return

I need to create a shared_ptr inside function and store it inside member class vector, but also I need to return it.
for example
create Person Class
class Person {
private:
std::string name;
public:
Person(std::string name) : name(std::move(name)) {}
const std::string &getName() const {
return name;
}
void setName(const std::string &name) {
Person::name = name;
}
};
then have another class that contains a vector of shared_ptr
class Agenda{
private:
std::vector<std::shared_ptr<Person>> people;
public:
std::shared_ptr<Person> addPerson(const std::string& name){
auto p = std::make_shared<Person>(name);
people.push_back(p);
return p;
}
};
so in my addPerson function I need to create the Person and add it to my vector, but also I need to return it. what is the best way do to this?
1.
create the local shared_ptr push in the vector and return, I suppose this is safe because I'm returning the shared_ptr as value but whats happen here, I'm creating two shared_ptr? one that lives inside the vector and the other that I'm returning?, also if the user of this functions reset the returned shared_ptr whats happen? will affect the shared_ptr inside the vector?
std::shared_ptr<Person> addPerson(const std::string& name){
auto p = std::make_shared<Person>(name);
people.push_back(p);
return p;
}
2.
use std::make_shared inside the push_back then find the element inserted and then return const reference to the Person not the shared_ptr, whats happen here?
const Person& addPerson(const std::string& name){
people.push_back(std::make_shared<Person>(name));
return *people.back();
}
maybe is best return a std::weak_ptr?
I want to know what is the best practice cons and pro to do this.

C++: how to make getters and setters work with an empty constructor

First of all, I have only learned a little bit of Java before. It's been only a few days since I started getting friendly with C++ so please don't take this question so basic and please don't degrade my question.
I made a simple source code as follows:
#include <iostream>
using namespace std;
class Car {
public:
void setBrand(string name);
void setPrice(double price);
string getBrand();
double getPrice();
Car();
Car(string name);
Car(string name, double price);
private:
string name;
double price;
};
Car::Car() {
}
Car::Car(string name) {
name = name;
}
Car::Car(string name, double price) {
name = name;
price = price;
}
void Car::setBrand(string name) {
name = name;
}
void Car::setPrice(double price) {
price = price;
}
string Car::getBrand(void) {
return name;
}
double Car::getPrice(void) {
return price;
}
int main() {
Car car;
car.setBrand("Nissan");
car.setPrice(30000);
cout << "Brand: " << car.getBrand() << endl;
cout << "Price: " << car.getPrice() << endl;
return 0;
}
I wanted to make a code that creates an empty instance of a class called Car, set the field values later and print them out on the console.
The code did not make any errors during the compile, but the result I see was totally different from what I expected. It didn't show the brand name and the price was looking even weird, as follows.
Brand:
Price: 6.95322e-310
Somebody help me out! Thank you very much indeed in advance.
The problem you have is that you override the member names with function parameters. You can use this-> to make it explicit or name the member differently.
For example:
void Car::setBrand(string name) {
this->name = name;
}
Or:
void Car::setBrand(string new_name) {
name = new_name;
}
In your constructor and setters, you make no differentiation between the local parameter and the class member.
name = name;
Both the function parameter and the class member are called name. Currently the compiler is assigning the parameter value to itself, and not affecting the class member at all. This is because the function parameter is in a more immediate scope.
Possible solutions:
Specify this when referring to the class member: this->name = name;.
Rename the function parameter: name = _name;.
For the constructor, use initializer lists:
Car::Car(string name, double price)
: name(name)
, price(price)
{ }
There's too much wrong with your code to describe it in prose, so let me present a fixed implementation, and I leave it to you to spot the difference:
#include <string>
class Car
{
private:
static constexpr double kNoPrice = -1.0;
static constexpr const char* kNoName = "[no name]";
public:
// Main constructor: constructs a car with the given name and price.
Car(std::string name, double price)
: name_(std::move(name))
, price_(price)
{}
// Convenience constructors:
Car() : Car(kNoName, kNoPrice) {}
Car(std::string name) : Car(std::move(name), kNoPrice) {}
// Accessors:
const std::string& getBrand() const { return name_; }
void setBrand(std::string name) { name_ = std::move(name); }
double getPrice() const { return price_; }
void setPrice(double price) { price_ = price; }
private:
std::string name;
double price;
};
Some random notes, in no particular order:
Use correct names. It's std::string, not string, mate or buddy. Never ever be abusing namespace std.
Include headers for external names that you need.
Reading uninitialized values is undefined behaviour, so none of your constructors should leave fields uninitialized (like price_).
Give private members consistent names (e.g. foo_ in my example).
Accessors should be const-correct.
Convenience constructors should delegate to one single work-horse constructor.
Pick sensible defaults for initial values of defaulted fields and make them discoverable.
Use move semantics when taking ownership of dynamically managed data (strings, dynamic containers, etc.).

Class member to point to a specific node member of an STL list?

How can I store a pointer to the name of a person's spouse as a private member of the person's class?
For example, say I have the following code:
#include <iostream>
#include <list>
using namespace std;
class person
{
private:
string name;
string *spouse;
public:
void setName(string tempName) { name = tempName; }
void setSpouse(string &tempSpouse) { spouse = &tempSpouse; } // ERROR HERE?
string getName() { return name; }
string getSpouse() { return spouse; } // ERROR HERE?
};
int main()
{
person entry;
list<person> personList;
list<person>::iterator itr1, itr2;
/* Adding two people/nodes to the linked list. */
entry.setName("John Doe");
personList.push_back(entry);
entry.setName("Tina Doe");
personList.push_back(entry);
/* Attempting to assign Tina Doe as John Doe's spouse. */
for (itr1 = personList.begin(); itr1 != personList.end(); itr1++)
{
if (itr1->getName() == "John Doe")
{
for (itr2 = personList.begin(); itr2 != personList.end(); itr2++)
{
if (itr2->getName() == "Tina Doe")
{
itr1->setSpouse(itr2->getName()); // ERROR HERE?
}
}
}
}
/* Displaying all Names with Spouses afterwards. */
for (itr1 = personList.begin(); itr1 != personList.end(); itr1++)
{
cout << "Name: " << itr1->getName() << " | Spouse: " << itr1->getSpouse() << endl;
}
return 0;
}
I am unable to assign the address of the spouses name to the pointer member in the class. I've noted in the comments where I believe the errors might be.
You can view the code and errors here: https://ideone.com/4CXFnt
Any help will be greatly appreciated. Thank you.
getName returns a temporary std::string (copy of the name variable), and the compiler is trying to save you from referencing a part of memory that will be soon deleted. This error has nothing to do with lists - to fix it you need to either store copies in spouse variable (which will result in storing same data in multiple places) or return a reference in getName. You can also consider creating another accessor (private one), but it's ugly.
I'd recommend storing copies, but if references/pointes are really required then it's sufficient to modify lines:
string getName() { return name; }
string getSpouse() { return spouse; } // ERROR HERE?
to
string& getName() { return name; }
string getSpouse() { return *spouse; } // ERROR HERE?
however, for consistency I'd recommend:
string& getName() { return name; }
string& getSpouse() { return *spouse; } // ERROR HERE?
You have two problems. The first is easy to fix: getSpouse doesn't return the right type. You should write
string getSpouse() { return *spouse; } // Derefencing the pointer and returning a string
// or
string* getSpouse() { return spouse; } // Returning the pointer
The second problem is more subtle. When you write: itr2->getName() , you only have a value (a copy of itr2->name): you do not store a variable that you will be able to change, so you cannot make a reference to it.
There is no easy way you can have a pointer in a class instance pointing the a private variable of another instance. I guess you should question the way you are doing things and create a pointer to the person and not to the name (remember pointer are cheap, they are just memory locations).
class person
{
private:
string name;
person *spouse;
public:
void setSpouse(person *_spouse) { spouse = _spouse; }
person* getSpouse() { return spouse; }
string getSpouseName() { return spouse->getName(); }
};
This work, but still it is not safe: if spouse is destroyed and try to access it from person, you will run into deep problems… (note that you had the same problem with the string).
So what is the fix? Well, if you only want B to be the spouse of A, you can create B first and make a reference in A with a constructor. But if you want B to be the spouse of A and A the spouse of B, you have to use either the unsafe trick above and be careful, or stock the spouses' list outside the class.

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.