Can I update an object inside an array? - c++

So I created an object and then added it into an array
Class Item{
...
};
Class Machine{
void setQuantity(int i);
};
Machine::Machine(){
Item items[5];
items[0] = a(int q);
}
I defined the setQuantity() and then tried to setQuantity later in the code, with
items[0].setQuantity(items[0].getQuantity() + 1);
but the quantity of a didn't update. Is it because I can't update a property of an item in an array or why can't the quantity change?
I'm thinking of changing the array into a vector, but I'm wondering if the problem is with the array or not. If it isn't then changing it into a vector won't matter does it?
Thanks in advance!
int Item::getQuantity(){
return quantity;
}
void Item::setQuantity(int q){
quantity = q;
}
items[i].setQuantity(items[i].getQuantity + 1);

I think the problem here is that you are declaring a variable inside a function call a(), which is, based on the code listed, undefined.
int q is the syntax for a variable declaration, but no value has been defined for q.
For each of the 5 items that you create, the default constructor of the class Item is called.
If you want to assign a value to items[0] you can (and probably should), for example, implement an assignment operator and a copy constructor in Item. Or you could store pointers to Item in the array instead of the objects themselves, and then use items[0] = new Item(...) to assign the items.

Related

Append and clear for a list c++

I'm trying to realize two methds append() and clear().
In appened(), I need to newPoint to the end of a list. If the list is empty, then adds newPoint as the first(and only) point in the list.
In clear(),I need to remove all the points in a list.
Can you give me some advice to realize appened and clear.
Here is a code:
//
#pragma once
const int maxListSize = 10;
class Point
{
private:
float x;
float y;
public:
Point(float x0 = 0, float y0 = 0)
{
x = x0;
y = y0;
}
};
class PointList
{
private:
//Data members
int size;
int cursor;
Point points[maxListSize];
public:
PointList();
//List Manipalution operations
void append(Point newPoint);
void clear();
~PointList();
};
*I don't need you to write everything for me, just give me some advice. I would like to realize it by myself. Thank you for helping.
Since you store your list elements by value (Point points[maxListSize]),
it is quite easy to do:
PointList() :size(0) {}
void append(Point newPoint) { points[size++] = newPoint; }
void clear() { size = 0; }
This assumes that your Point object doesn't manage any resource, which is true for this particular example. Otherwise, inserted Point objects should be destroyed in clear.
To get the semantics that you're probably expecting for appending new items, and clearing out existing items, I suggest you look at the placement new operator, and manually calling the destructor of an item in the list.
Currently your class will construct all of the items in the list when you create the list. This can be quite time consuming for complex structures. Then, instead of the constructor for your elements being called, you'll instead be calling the copy-assignment operator, as the items are already constructed.
If you store your array as
char * points[sizeof(Point)*maxListSize];
Any only initialize the items when they're actually added, you avoid the construction cost when you create the list.
Your append function takes it's argument by value. Instead, I recommend you have two append functions. One that takes const&, and the other that takes an rvalue-reference. Then, inside the append function, call the placement new operator on the address of the next location in your array.
To clear the array, simple call the destructor for each element in the array one at a time.

Items are not adding to vector c++

class Way {
private:
std::vector<Node> nodesCollection;
public:
Way();
Way(const Way& orig);
virtual ~Way();
void SetNodesCollection(std::vector<Node> nodesCollection);
std::vector<Node> GetNodesCollection() const;
};
I added vector as a property and I'm accessing that vector from following class and adding items.
Way wayNode;
for (; WayIter!=wayNodes.end(); ++WayIter)
{
const JSONNode& arrayNode = *WayIter;
if (arrayNode.find("ref") != arrayNode.end() )
{
std::string id = arrayNode.find("ref")->as_string();
if(nodesMap.find(id) != nodesMap.end())
{
wayNode.GetNodesCollection().push_back(nodesMap.find(id)->second);
}
}
}
but items are not adding to "nodesCollection". its count is zero. that adding object is not null.
I need some help to sort out this. I'm new to c++.
Thanks in advance.
You need to read about pass by value vs pass by reference. GetNodesCollection is returning a brand new copy of the vector. Then you add your nodes to this new copy, instead of to the original.
Well, maybe it is more return by value vs return by reference. Anyway the point is that you are getting a brand new copy instead of a reference to the original vector.
One way to fix would be to change the return type to a reference (you'd have to make the same change where GetNodesCollection is defined)
std::vector<Node>& GetNodesCollection();

Passing object by pointer and modifying it isn't changing state of the object

Code is below. I have a data member called book_b and within the function OB::x() this unordered_map gets objects inserted. On the first insertion the key is 10 and the new object inserted at key=10 works fine. However, when key=10 appears again, I am anticipating a new object would be created and inserted at key=10 (replacing the previous object at key=10). However, once OB::x() returns, when we are back in OB::y() it is as if the new object had never been inserted.
I thought this should work because I am passing the book_b object by pointer to the function modifying its state? I'm worried there's something wrong with my fundamental understanding.
class OB{
public:
void y(O lo);
void x(std::unordered_map<int, PL>* book, int a, long b);
private:
std::unordered_map<int, PL> book_b;
std::unordered_map<int, PL> book_a;
};
void OB::y(O lo){
//Code which obtains parameters to use in x() from lo
int a = o.getA();
long b = o.getB();
//This is the data member the below function will insert an object in to
std::unordered_map<int,PL>* book = &book_b;
//This is the function which should be changing the state of book.
//It works on the first call (when a new object is inserted) but on repeated calls
//(where the object may be replaced with a new object with the same key) it acts
//as if the new key-value pair wasnt replacing the existing key-value pair.
x(book, a, b);
}
//Works when book is empty and we insert a new PL object, however, when I go to "overwrite"
//an existing PL object with the same key (a) it doesn't hold state once the function returns
void OB::x(std::unordered_map<int,PL>* book, int a, long b){
PL temp;
temp.setQuantity(b);
book->insert(std::make_pair(a, temp));
}
std::unordered_map::insert does not insert a new element if one with the same key already exists.
auto p = book->insert(std::make_pair(a, temp));
std::cout << std::boolalpha;
std::cout << "Did insert succeed? " << p.second << std::endl;
If you want to update an existing element if one exists, use operator[]:
(*book)[a] = temp;
Note: you don't need to pass pointers, unless you want to allow for the possibility of nullptr being passed. It is simpler to use references:
void OB::x(std::unordered_map<int,PL>& book, int a, long b) { ... }
x(book_b, a, b);
std::unordered_map::insert "inserts element(s) into the container, if the container doesn't already contain an element with an equivalent key."
Change
book->insert(std::make_pair(a, temp));
to
(*book)[a] = temp;
and also note that passing by reference instead of pointer would be more reasonable here and make your code much cleaner :)

classname as an object to vector and argument to function to push_back

I have this small program as i am trying to understand the vector and the classname being passed as an argument. Here is the program:
#include<iostream>
#include<vector>
using namespace std;
class objectclass{
public:
void vec_try(){
cout<<"print out something";
}
};
class another{
public:
void run();
vector<objectclass *>ports;
void add_obj(objectclass *p){
ports.push_back(p);
}
};
void another::run(){
//int j=0;
ports[j]->vec_try();
}
int main(){
another a;
a.run();
system("pause");
return 0;
}
i have idea that passing classname in vector as an object is fine and then using push_back to insert the element in that vector but in the function add_obj(objectclass *p) how do i pass the values if i dont want to change the defination of the function. i know a way like this:
objectclass *p;
p= new objectclass[10];
but my function has already defination and also i want to call the function vec_try() with ports[i] so i am not getting how to pass the values and the how this is working with ports[i]. i basically need some clarification on this.
Your add_obj function takes pointers to objectclass objects. So to add elements to your vector, you need to do:
another a;
objectclass obj1; // Create an objectclass
a.add_obj(&obj1); // Pass its address to add_obj
objectclass obj2;
a.add_obj(&obj2);
objectclass obj3;
a.add_obj(&obj3);
Of course, your vector is keeping pointers to these objects. When these objects go out of scope and are destroyed, these pointers will be left pointing at invalid object. But that doesn't matter here, because your objects are only destroyed at the end of main.
An alternative would be to dynamically allocate your objects:
another a;
a.add_obj(new objectclass());
a.add_obj(new objectclass());
a.add_obj(new objectclass());
Each line dynamically allocates an objectclass object, then passes a pointer to that object to add_obj. However, you will need to make sure that you eventually delete this objects in some way or another.
The first element that you push_back into the vector will have index 0, the second will have index 1, the third will have index 2, and so on.
If in run, you want to iterate over all objects in the vector, you can do it something like this:
for (int i = 0; i < ports.size(); i++) {
ports[i]->vec_try();
}
As you can see, this loops through all the elements in the vector (from 0 to ports.size()) and calls vec_try on each one.
There is a better way to do this using iterators, but I'll leave that for a future lesson.

Need to make an array of already created objects

I am making several items, and need to set them as being interactable with each other.
Item i1 = Item("Item 1");
Item i2 = Item("Item 2");
Item i3 = Item("Item 3");
Item i4 = Item("Item 4");
i1.setInteractable({i2,i3});
i2.setInteractable({i1,i4});
i3.setInteractable({i1});
This is the method header for the setInteractable method in Item.
void setInteractable(Item i[]);
The interactable items are stored as such:
static Item interactableItems[25];
This doesn't work, the error occurs after the first curly brace. What is the correct way to do this in C++?
You don't want to store objects in your array (otherwise, they are copied), but references to objects.
Change your storage and interface like that:
void setInteractable(Item& i[]);
static Item& interactableItems[25];
I advise to look in google for:
copy constructor
pointer vs object vs reference
C++ doesn't make dynamic lists as easily as you are trying.
To make the dynamic lists you need to first declare a dynamic list:
Item * dlist = new Item[2];
Set them:
dlist[0] = i1;
dlist[1] = i2;
then pass them into your function:
setInteractable(dlist);
Finally you have to remember to clean your memory:
delete [] dlist;
Or... you do this with the standard template library.
std::vector<Item> temp1;
temp1.push_back(i1);
//... other sets
Your function should be:
void setInteractable(std::vector<Item> & list)
{
///
}
The call should be
setInteractable(temp1);
It's a wrong C++ syntax to pass an array initialization like that:
i1.setInteractable({i2,i3}); // error: invalid
In various way you can achieve this. The most straight forward way is to use std::vector.
First declare interactableItems as,
static vector<Item> interactableItems;
Now you don't need setInteractable(), if you make above variable public
Usage:
i1.interactableItems.push_back(Item("Item 2"));
i1.interactableItems.push_back(Item("Item 3"));
If you want to have variable private then you can just put a wrapper and put the push_back inside it.
I would solve the problem like so:
Change the method to work on one object at a time, and loop over them:
void setInteractable(Item &i);
for (int i = 0; i < 25; i++)
for (int j = i + 1; j < 25; j++)
items[i].setInteractable(items[j]);
Much cleaner to deal with. You can store them in a std::vector inside of the Item, and just with those.
I would suggest using one of the STL containers. My implementation will proceed thus:
// Method header for the setInteractable method
#include <vector>
class Item {
private:
// some declarations
public:
void setInteractable(vector<Item &>);
// some other declarations
};
Your implementation should them selectively push Item objects onto vectors before passing them into the function.
Refer to the Cplusplus Reference Site for some more readings on STL containers.