How do i change an object through the use of pointers? - c++

#include "Visit.h"
class Patient
{
private:
std::string name;
std::string IC;
List<Visit> *visitList;
List<MC> mcList;
public:
Patient();
Patient(std::string, std::string);
void addVisit(Visit);
List<Visit> *getVisitList();
};
//End of Patient.h
#include "Patient.h"
Patient::Patient()
{
visitList = new List<Visit>();
}
Patient::Patient(std::string ic, std::string n) : name(n), IC(ic)
{
visitList = new List<Visit>();
}
void Patient::addVisit(Visit v)
{
visitList->add(v);
}
List<Visit> * Patient::getVisitList()
{
return visitList;
}
//End of Patient.cpp
class Visit
{
private:
__int64 time;
double cost;
bool xRayStatus = false;
public:
Visit();
Visit(__int64, double);
void addXRay();
bool getXRayStatus();
};
//End of Visit.h
#include "Visit.h"
Visit::Visit() {
}
Visit::Visit(__int64 t, double c) : time(t), cost(c) {
}
void Visit::addXRay()
{
xRayStatus = true;
}
bool Visit::getXRayStatus()
{
return xRayStatus;
};
//End of Visit.cpp
int main()
{
int pos;
Visit v(/*current time, cost*/);
Patient p()
unordered_map<string, Patient> patientMap;
string IC;
getline(cin,IC);
Patient p(IC, "John");
patientMap.insert({IC, p});
Patient *pc;
Visit *vc;
pos = patientMap[IC].getVisitList()->getLength();
pc = &patientMap[IC];
pc->addVisit(v); //Debugger shows patientMap[IC].getVisitList()->getLength() becomes 2
pc->getVisitList()->get(pos).addXRay(); //patientMap[IC].getVistList()->get(0).getXRayStatus() still false
vc = &patientMap[IC].getVisitList()->get(pos);
vc->addXRay(); //patientMap[IC].getVistList()->get(0).getXRayStatus() still false
}
How do i make that getXRayStatus true? It seems odd to me that i can add items into the list but not carry out other functions like vc->addXRay.
vc itself shows true but the change isn't reflected on my map.
pc somehow is able to add Visits and show the change on the map.

In the List<Visit> you are keeping instances of Visits. When you are setting the xRayStatus you are changing the status of the local Visit copy you get from the list, not to the actual object in the list.

In an extended comment conversation, the asker has asked for general redesign help to avoid the problems caused by working with a Visit copy from get(). My redesign suggestions are:
stop using List. Whether you wrote it yourself or got it somewhere else, it's surely more than you need. Use std::vector<> as the collection class of first choice, and change to something else only when you need it.
don't keep pointers to your collections in Patient unless they are likely to be enormous memory hogs. Have vectors as member variables. This will save you having to write a lot of cleanup code.
Stop keeping solid Visit objects in the collections. Use make-shared() or make_unique to get yourself smart pointers to visit objects that are on the heap. Keep these pointers in the vectors and you can deference them to change the real values in the real visits out on the heap
consider adding a date and time or visit number to Visit since at the moment it's not clear to me how you find a specific visit when there is more than one
set properties in things before you put them in collections. Your main knows all about the inside of a Visit (not that I approve of that) but has Patient create an empty one and then jumps through hoops trying to get hold of it and change some of its properties. Why not have Patient set those properties? Or have main() create a Visit, fill in all the properties, and then hand it to Patient saying "here, add this to your collection"? What you're doing now is so much harder than it needs to be.
Finally, find a tutorial, book, or online course that works for you and gets you clear on the difference between objects and pointers, good reasons for using pointers, the need for destructors (you have none at the moment) and for good measure explains the collection classes in std:: and elsewhere. Tutorials and architectural advice are not a good fit for the Q&A mechanism of StackOverflow.

Related

Populating a vector of objects within a class

and I've hit my first wall on my coding project/assignment.
I'm to implement functionality into code that's been done to some stage, and I cannot alter the given code so I have to work around the given structure.
The code, in a nutshell, reads family relations from a text file and populates database with the family relation data and later on allows user to print out information he wants to access.
What I'm having trouble with is understanding how I can and how I have to utilize a struct given to me in the assignment. The struct is
struct Person
{
std::string id_ = NO_ID;
int height_ = NO_HEIGHT;
std::vector<Person*> parents_{nullptr, nullptr};
std::vector<Person*> children_;
};
and I'm using it at least in the initialization phase of the data structure.
I start by calling the process in main.cpp with
database->addRelation(it->child_, it->parents_, std::cout);
In the naming/height adding phase I'd simply do it with
MyPerson.id_ = id;
MyPerson.height_ = height;
where MyPerson is defined by Person MyPerson;
but as far as I can tell, I have to somehow access the object pointers to be able to populate the vectors for when I want to add children/parents to the person.
The class functions that are called when initializing person's name, height and family relations are these two:
void Familytree::addNewPerson(const string &id, const int &height, ostream &output)
{
MyPerson.id_ = id;
MyPerson.height_ = height;
}
void Familytree::addRelation(const string &child,
const std::vector<string>
&parents, ostream &output)
{
}
The addRelation fuction is what I'm having a hard time getting to work. Simply appending the strings to it won't work since it expects Person* -objects, which are, as far as I can tell, just pointers to the other Persons, but I'm not sure how I can access them.
Also, let me know if anything here is excessive or if I'm missing anything crucial, I'll edit it to the best of my ability
Editing with additional information:
The only things I've added myself that can be seen here is
Person MyPerson;
and the contents of the class function addNewPerson. The other snippets I can not change in any shape or form.
Edit#2
Current progress, debatable whether I'm closer or further from the goal
My persons map is using Personmap = std::map<std::string, Person >;
and I'm using it in addNewPerson with
persons_[id] = id;
persons_[id] = height;
, but I'm still randomly trying different things to try and make it work for the next phase where I need to somehow add the objects to the vectors.
The biggest problem I have is the fact that I do now know how to play around the difference of *Person and Person

What is a good way of tracking a variable size subset of a large variable size vector in c++

As part of a simulation I'm currently iterating through a large vector of objects looking for those that have an attribute. It seems to me that it would be faster to store the addresses of those objects in another vector of pointers until I no longer need to operate on them... example code would looks like this... I'm not sure about the erase part.
public:
bool studying = false;
void study();
};
void student::study()
{
//Read a book
studying = false;
};
int vector_question_main(int argc, char* argv[])
{
std::vector<student> masterList;
std::vector<student*> studyingList;
student lazy1;
student good1;
good1.studying = true;
student* s = &masterList.at(1);
studyingList.push_back(s);
for (int i = 0; i < studyingList.size(); i++)
{
studyingList.at(i)->study();
if (studyingList.at(i)->studying == false)
{
studyingList.erase(i);
}
}
}
Am I on the right track or is there a "better" way? To help define my situation I won't know in advance how many objects I have or how many I need to track. I will need to iterate over and operate on them allot.
Edit:
Thanks for the initial responses.
#PaulMcKenzie
The hard requirements/statements of qualities I need from my collection of objects so far is that...
it's easily re-sizeable due to wanting to add/remove objects
frequently.
I can iterate over the collection (in no particular order) performing
some action such as getting/setting an attribute or calling a method.
A objects method will only perform some action on its own attributes
based on its own attributes or parameters.
I expect a future requirement will be that I want to only iterate over a smaller subset. prematurely optimising. Thanks #Jack Deeth

c++ returning object from function?

Absolute newbie to c++ (and oop) as well.
Just wanted to ask how to return an object from a list (if it exists), by passing a single id to a getter.
My code is as follows:
class Customer
{
private:
unsigned int custNo;
std::string name;
std::string address;
/* .. */
}
class Store
{
private:
std::string storeName;
std::list<Customer *> customerBase;
std::list<Product *> productStock;
std::list<Sale*> sales;
public:
Store(std::string storeName); // constructor
std::string getStoreName();
Customer & getCustomer(unsigned int custId); //METHOD IN QUESTION
/*..*/
// Constructor
Customer::Customer(std::string name, std::string address)
{
//ctor
}
//
Customer & Store::getCustomer(unsigned int custId){
}
I know this might be a farily basic question. Still I would very much appreciate the help. Thanks in advance!
Just wanted to ask how to return an object from a list (if it exists), by passing a single id to a getter.
Pointer is the first thing that you should think when you see "if it exists". This is because the only representation of an object in C++ that can be optional is a pointer. Values and references must always be present. Therefore, the return type of your function should be Customer*, not Customer&:
Customer* Store::getCustomer(unsigned int custId){
...
}
If you need fast retrieval by an id, use a map<int,Customer*> or unordered_map<int,Customer*>. You could do it with a list, too, but the search would be linear (i.e. you would go through the entire list in the worst case).
Speaking of pointers, if you must store pointers to Customer objects, assuming that the objects themselves are stored in some other container, you may be better off using shared_ptr<Customer> in both containers, to simplify resource management.
You can do this but it would be cumbersome as list is not sorted so you have to traverse the list and check each structure for matching id.
Rather you could store these in std::map with ids as their keys...OR much better unordered_map if you really care about performance.
Assuming you have getCustId() public member function in class Customer:
Customer & Store::getCustomer(unsigned int custId){
auto custIt = find_if(customerBase.begin(), customerBase.end(),
[custId](const Customer& c){ return c.getCustId() == custId });
return *custIt;
}

How to create method which will know that its instance is in matrix of another class

I'm an absolute beginner in OOP (and C++). Trying to teach myself using resources my university offers for students of higher years, and a bunch of internet stuff I can find to clear things up.
I know basic things about OOP - I get the whole point of abstracting stuff into classes and using them to create objects, I know how inheritance works (at least, probably the basics), I know how to create operator functions (although as far as I can see that only helps in code readability in a sense that it becomes more standard, more language like), templates, and stuff like that.
So I've tried my first "project": to code Minesweeper (in command line, I never created a GUI before). Took me a few hours to create the program, and it works as desired, but I feel like I'm missing a huge point of OOP in there.
I've got a class "Field" with two attributes, a Boolean mine and a character forShow. I've defined the default constructor for it to initialize an instance as an empty field (mine is false), and forShowis . (indicating a not yet opened filed). I've got some simple inline functions such as isMine, addMine, removeMine, setForShow, getForShow, etc.
Then I've got the class Minesweeper. Its attributes are numberOfColumns, ~ofRows, numberOfMines, a pointer ptrGrid of type Mine*, and numberOfOpenedFields. I've got some obvious methods such as generateGrid, printGrid, printMines (for testing purposes).
The main thingy about it is a function openFiled which writes the number of mines surrounding the opened field, and another function clickField which recursively calls itself for surrounding fields if the field which is currently being opened has 0 neighbor mines. However, those two functions take an argument -- the index of the field in question. That kinda misses the point of OOP, if I understand it correctly.
For example, to call the function for the field right to the current one, I have to call it with argument i+1. The moment I noticed this, I wanted to make a function in my Field class which would return a pointer to the number right to it... but for the class Field itself, there is no matrix, so I can't do it!
Is it even possible to do it, is it too hard for my current knowledge? Or is there another more OOP-ish way to implement it?
TLDR version:
It's a noob's implemetation of Minesweeper game using C++. I got a class Minesweeper and Field. Minesweeper has a pointer to matrix of Fields, but the navigation through fields (going one up, down, wherever) doesn't seem OOP-ishly.
I want to do something like the following:
game->(ptrMatrix + i)->field.down().open(); // this
game->(ptrMatrix + i + game.numberOfColumns).open(); // instead of this
game->(ptrMatrix + i)->field.up().right().open(); // this
game->(ptrMatrix + i + 1 - game.numberOfColumns).open(); // instead of this
There are a couple of ways that you could do this in an OOP-ish manner. #Peter Schneider has provided one such way: have each cell know about its neighbours.
The real root of the problem is that you're using a dictionary (mapping exact coordinates to objects), when you want both dictionary-style lookups as well as neighbouring lookups. I personally wouldn't use "plain" OOP in this situation, I'd use templates.
/* Wrapper class. Instead of passing around (x,y) pairs everywhere as two
separate arguments, make this into a single index. */
class Position {
private:
int m_x, m_y;
public:
Position(int x, int y) : m_x(x), m_y(y) {}
// Getters and setters -- what could possibly be more OOPy?
int x() const { return m_x; }
int y() const { return m_y; }
};
// Stubbed, but these are the objects that we're querying for.
class Field {
public:
// don't have to use an operator here, in fact you probably shouldn't . . .
// ... I just did it because I felt like it. No justification here, move along.
operator Position() const {
// ... however you want to get the position
// Probably want the Fields to "know" their own location.
return Position(-1,-1);
}
};
// This is another kind of query. For obvious reasons, we want to be able to query for
// fields by Position (the user clicked on some grid), but we also would like to look
// things up by relative position (is the cell to the lower left revealed/a mine?)
// This represents a Position with respect to a new origin (a Field).
class RelativePosition {
private:
Field *m_to;
int m_xd, m_yd;
public:
RelativePosition(Field *to, int xd, int yd) : m_to(to), m_xd(xd),
m_yd(yd) {}
Field *to() const { return m_to; }
int xd() const { return m_xd; }
int yd() const { return m_yd; }
};
// The ultimate storage/owner of all Fields, that will be manipulated externally by
// querying its contents.
class Minefield {
private:
Field **m_field;
public:
Minefield(int w, int h) {
m_field = new Field*[w];
for(int x = 0; x < w; x ++) {
m_field[w] = new Field[h];
}
}
~Minefield() {
// cleanup
}
Field *get(int x, int y) const {
// TODO: check bounds etc.
// NOTE: equivalent to &m_field[x][y], but cleaner IMO.
return m_field[x] + y;
}
};
// The Query class! This is where the interesting stuff happens.
class Query {
public:
// Generic function that will be instantiated in a bit.
template<typename Param>
static Field *lookup(const Minefield &field, const Param &param);
};
// This one's straightforwards . . .
template<>
Field *Query::lookup<Position>(const Minefield &field, const Position &pos) {
return field.get(pos.x(), pos.y());
}
// This one, on the other hand, needs some precomputation.
template<>
Field *Query::lookup<RelativePosition>(const Minefield &field,
const RelativePosition &pos) {
Position base = *pos.to();
return field.get(
base.x() + pos.xd(),
base.y() + pos.yd());
}
int main() {
Minefield field(5,5);
Field *f1 = Query::lookup(field, Position(1,1));
Field *f0 = Query::lookup(field, RelativePosition(f1, -1, -1));
return 0;
}
There are a couple of reasons why you might want to do it this way, even if it is complicated.
Decoupling the whole "get by position" idea from the "get neighbour" idea. As mentioned, these are fundamentally different, so expose a different interface.
Doing it in this manner gives you the opportunity to expand later with more Query types in a straightforwards fashion.
You get the advantage of being able to "store" a Query for later use. Perhaps to be executed in a different thread if it's a really expensive query, or in an event loop to be processed after other events, or . . . lots of reasons why you might want to do this.
You end up with something like this: (C++11 ahead, be warned!)
std::function<Field *()> f = std::bind(Query::lookup<RelativePosition>,
field, RelativePosition(f1, -1, -1));
. . . wait, what?
Well, what we essentially want to do here is "delay" an execution of Query::lookup(field, RelativePosition(f1, -1, -1)) for later. Or, rather, we want to "set up" such a call, but not actually execute it.
Let's start with f. What is f? Well, by staring at the type signature, it appears to be a function of some sort, with signature Field *(). How can a variable be a function? Well, it's actually more like a function pointer. (There are good reasons why not to call it a function pointer, but that's getting ahead of ourselves here.)
In fact, f can be assigned to anything that, when called, produces a Field * -- not just a function. If you overload the operator () on a class, that's a perfectly valid thing for it to accept as well.
Why do we want to produce a Field * with no arguments? Well, that's an execution of the query, isn't it? But the function Query::lookup<RelativePosition> takes two arguments, right?
That's where std::bind comes in. std::bind essentially takes an n-argument function and turns it into an m-argument function, with m <= n. So the std::bind call takes in a two-place function (in this case), and then fixes its first two arguments, leaving us with . . .
. . . a zero-argument function, that returns a Field *.
And so we can pass around this "function pointer" to a different thread to be executed there, store it for later use, or even just repeatedly call it for kicks, and if the Position of Fields was to magically change for some reason (not applicable in this situation), the result of calling f() will dynamically update.
So now that I've turned a 2D array lookup into a mess of templates . . . we have to ask a question: is it worth it? I know this is a learning exercise and all, but my response: sometimes, an array is really just an array.
You can link the four neighbours to the cell via pointers or references. That would likely happen after the playing field has been created. Whether that's good or bad design I'm not sure (I see the same charme though that you see). For large fields it would increase the memory footprint substantially, because a cell probably doesn't hold that much data besides these pointers:
class Cell
{
// "real" data
Cell *left, *right, *upper, *lower;
// and diagonals? Perhaps name them N, NE, E, SE, S...
};
void init()
{
// allocate etc...
// pseudo code
foreach r: row
{
foreach c: column
{
// bounds check ok
cells[r][c].upper = &cells[r-1][c];
cells[r][c].left = &cells[r][c-1];
// etc.
}
}
// other stuff
}

List structure for c++ game

I'm making a very very basic game in C++ to gain some experience in the language and I have hit a bit of a brick wall in terms of progress.
My problem is, while I was designing a class for the player's weapons, I realized I required a list, as I will only have a certain number of weapons throughout the game.
So I ask you, if you were designing this, what implementation would you use for storing all of the weapons in a game? Why?
Here is my code so far for the weapons. as you can see I was just about to start defining all of them manually, starting with the "DoubleBlades"... (Edit* I forgot to note that players should be able to have more than one wepaon, and they can pick up more or drop some, so the list can grow and shrink)
#ifndef __WEAPON_H__
#define __WEAPON_H__
#include <string>
class Item
{
public:
Item(const std::string& name)
: name(name){ }
const std::string& getName(void) const { return name; }
int getID(void) const { return this->itemID;}
private:
std::string name;
int itemID;
};
class Weapon
: public Item
{
private:
int damage;
public:
Weapon(const std::string& name)
: Item(name) { }
virtual int getDamage(void) const = 0;
};
class DoubleBlades
: public Weapon
{
public:
DoubleBlades(int ammo)
: Weapon("DoubleBlades") { }
virtual int getDamage(void) const { return 12; }
};
#endif
Also if you spot any bad habits I would really appreciate letting me know.
I would use the standard implementation (std::list<Item*>) because it's easy to use ("out of the box") and, out of the standard containers, it seems to be most suitable:
You probably need support for fast adding/deleting of weapons (so no std::vector or C arrays)
You probably don't need support for fast searching of the list for a specific item (so no std::map)
BTW you need to have a virtual destructor in the Item class (this is a general rule on base classes in c++).
Oh, and another minor problem - i think the Weapon class does not need the damage member variable - the class doesn't use it and it has private access, so the deriving classes cannot use it either.
You might have to use dynamic_cast in your implementation - a virtual environment such as yours will probably require "safe" casting of pointers from Item* to Weapon*.
On a very basic level, you may not necessarily need a data structure. For instance, if you know exactly how many weapons, etc. you need/may possibly have, you can (wastefully) allocate an array of size n and have certain spots in the array as a pointer to a weapon (if you currently have that weapon, else NULL). Then, simply cast appropriately based on weapon index. But this is a naive approach. Otherwise, refer to Mike's comment above on the original post.
If the list is going to vary in size, I'd use either an std::vector or and std::set. With both, you'll get to use all the nice stl functions and what not. If you use set, it will be quicker to sort the "weapon objects". The vector is more useful if you want to know the order in which a particualr object was added.
If they are going to have a fixed number of weapons you can still use a vector or a set, just make sure you pass the exact size you're going to use to the constructors. This will allow for some optimizations like allocating contiguous blocks of memory (which speeds up access times).
You might actually look at std::map, -- consider something like
std::map<std::string, Item*>
This would allow you to access items by name, which can be nice syntactic sugar, and would allow you to quickly check for existence of an item using the count method.