Trouble calling an object's method using a pointer to that object - c++

So I normally wouldn't bother posting about such a simple thing but I can't for the life of me figure out what I'm doing wrong and it's probably something very simple that i'm over looking.
Getting straight to the point, I'm making an object pointer and then using that pointer to call a method of that particular object.
But for some reason whenever I cout the function as follows:
Entry FirstEntry = Entry(J1,H1);
cout << FirstEntry.getItem() << endl;
cout << FirstEntry.getKey() << endl;
Entry *siz = new Entry();
cout << siz->getItem() << endl;
It gives me a blank line being output. Whereas it should be giving me my item value.
The Object itself looks like such:
Entry::Entry()
{
}
Entry::Entry(KeyType & Key, ItemType & newItem)
{
setKey(Key);
setItem(newItem);
}
Entry::~Entry()
{
}
ItemType Entry::getItem() const
{
return item;
}
KeyType Entry::getKey() const
{
return searchKey;
}
void Entry::setItem(const ItemType & newItem)
{
item = newItem;
}
void Entry::setKey(const KeyType & Key)
{
searchKey = Key;
}
I've been staring at this code for awhile and I can't quite figure out what's causing it to output just a blank line.
Thank you very much for your patience,

Okay, thanks to the two posts it's super obvious what I'm doing wrong here, when I created my pointer to my object I was pointing towards the constructor which didn't set any values and thus when I was returning values through my pointer technique it was giving me the accurate values. They were just empty values, hence it was putting out an empty line.
The Fix:
Entry *siz = new Entry(J1,H1); //This line didn't hold parameters to call right constructor
cout << siz->getItem() << endl;

Related

shared pointer swap method identity change

Background:
I donot know what caused me to experiment with this, but I am trying to test a containerised linked list which internally uses smartpointers.
Here is the repl link:
https://repl.it/#BasavarajNagar/GoodnaturedGlisteningSection-1
#include <memory>
using namespace std;
template<typename T>
class linkedlist {
private:
class node {
public:
T data;
shared_ptr<node> next;
node(T data) {
this->data = data;
}
};
// non const unique ptr
shared_ptr<node> head;
public:
void add(T data) {
cout<< "adding " << endl;// + data << endl;
if (head == nullptr) {
head = shared_ptr<node>(new node(data));
return;
}
shared_ptr<node> cursor;
cursor.swap(head);
// this works well
while (cursor != nullptr) {
cout << cursor->data << endl;
cursor = cursor->next;
}
cout << data << endl;
// this is the problematic assignment
cursor = shared_ptr<node>(new node(data));
}
void trace() {
shared_ptr<node> cursor;
cursor.swap(head);
cout << "trace" << endl;
while (cursor != nullptr) {
cout << cursor->data << endl;
cursor = cursor->next;
}
}
};
int main() {
std::cout << "Hello World!\n";
linkedlist<int> ll;
ll.add(22);
ll.add(45);
ll.add(63);
ll.trace();
}
The trace method always points to last element, the head is lost after swap during add method.
Note:
I know this is not production quality code, but to understand internals/quirks of smartpointers. So, pls avoid code quality comments.
You badly misunderstand shared pointers. https://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr
The trace info you need most is node::node and node::~node. Tracking when actual nodes get created and destroyed will help you. You also must understand scope.
A quick critique of your "add" function (fixes left to you, beyond the scope of the question and detrimental for me to post too much):
It creates a single item list correctly. However, if you try to add again, you move head to a temporary object, setting head to nullptr. You then loop cursor through the list, destructing any nodes that might have existed, until there are no more. The fact that you have just assigned nullptr to cursor is not a problem, because you immediately toss whatever value it might have had as you then create a new list with a single item, held by cursor instead of head. You then go out of scope, destructing cursor, and therefore also destructing that new item that you just added to cursor.
But the biggest problem is your trace function, which you are using to understand your list, but it's not doing anything remotely like what you want. This is the biggest problem, because you think you understand what is going on based on bad information. If trace lies to you, then you can't get anywhere using it to understand add.
Here is a trace function which will correctly print the current contents of your list, without destroying it:
void trace() {
cout << "trace: ";
shared_ptr<node> cursor = head; // SHARE, do not lose head, read the docs
while (cursor.get()) {
cout << cursor->data << ", ";
cursor = cursor->next;
}
cout << endl;
}
I would suggest calling the trace function twice in a row. If it's not destroying the list as it prints it, then the second call should have the same output as the first. To fix add, you need to simplify it. Just follow what you should do on a regular node pointer. Your big problem was using "swap" to place your actual data under the sole control of a temporary object, which will quickly DO ITS JOB, which is destroy all your data.

Trying to write my own linked list impementation in c++, code segfaults after hitting 3 elements in the list

I've been trying to write my own implementation of linked list, but the code segfaults when I try to access an the third element or anything after it. Adding elements doesn't segfault, but accessing does. I can't find the pointer error in my get() function.
Each node in the list stores data (of Template t) and a pointer leading to the next node. I have two functions for everything- one for the first element, and one for any subsequent elements. The get() function for the subsequent elements always segfaults. I have some debug messages in the function that spit out results I can't explain. For example, if I run a get() request for the second element, an then the third, the code doesn't segfault, but it does return clearly incorrect results. Debug messages I placed indicate the segfault occurs when the second element calls the function to check the third element, if it occurs at all. Try the code with and without the line cout << newList.get(2) << endl; and you'll get very different results.
One possible cause is the pointer storage- I have the get() function output the pointer of each element (except the first) as it cycles through, and compare them to the pointers outputted by the add() function, and and pointers for element 0 and 1 match, but 2 and beyond do not match, and I can't seem to figure out why that would be.
#include <iostream>
using namespace std;
template <class T> class myLinkedList{
T data;
myLinkedList<T> *next = NULL;
public:
myLinkedList(T input){
data = input;
}
void add(T input){
if(next == NULL){
myLinkedList<T> newItem(input);
next = &newItem;
cout << "adding to list, data is " << input << ", pointer is " << next << endl;
}else{
myLinkedList<T> nextEntry = *next;
nextEntry.add(input);
}
}
T getData(){
return data;
}
//the start of the get function, only used by the first entry in the list
T get(int entry){
int currentPosition = 0;
if(entry == currentPosition){
return getData();
}else{
//defrefrence the pointer anc check the next entry
myLinkedList<T> nextEntry = *next;
return nextEntry.get(entry, ++currentPosition);
}
}
private:
//this vesion is the hidden, private vesion only used by nodes other than the first one
//used to keep track of position in the list
T get(int entry, int currentPosition){
//cout << currentPosition << endl;
if(entry == currentPosition){
return data;
}else{
//derefrence the pointer and check the next entry
cout << next << endl;
myLinkedList<T> nextEntry = *next;
currentPosition++;
T output = nextEntry.get(entry, currentPosition);
return output;
}
}
};
int main(){
myLinkedList<int> newList(3);
newList.add(4);
newList.add(5);
newList.add(7);
newList.add(9);
cout << newList.get(2) << endl;
cout << newList.get(3) << endl;
return 0;
}
Results are clearly erroneous- program should spit oout two macthing sets of pointers, as well as the numbers 5 and 7 ( the list elements)
One of your main problems is here:
if(next == NULL){
myLinkedList<T> newItem(input); // <<<<<<<<<<<<<
next = &newItem;
cout << "adding to list, data is " << input << ", pointer is " << next << endl;
}
you allocate an item on stack inside the if scope. Then you make next to point to this item. But... lifetime of the item is bounded by this scope. As son as you exit the scope, this item does not exist any longer. You need to allocate it dynamically by 'new' or other methods.
I had a breakthrough! Following Serge's solution was helpful, but one more change was needed- rather than create a function reference in the else block of my add function,
eg
myLinkedList<T> nextEntry = *next;
nextEntry.add(input)
i needed to use the pointer directly, as in
next->add(input)
I didn't know my pointer/object syntax

I'm trying to check if a getter for a class vector is working by printing it but it won't work

I made a class called "Item" and a class called "Room" and there's a vector for Item types called "Items" inside Room.
I added a few Items into the Item vector and tried to make a getter for that Item Vector. Now i'm trying to print the getter to see if it really did get what i wanted but it gives me an error message when i try one way or just prints nothing when i try a different way. What am i doing wrong?
Room.h has some stuff as well as these lines of code:
.....
///Getters
//get a list of the items currently in the room
vector<Item> GetItems();
private:
///properties
string RoomName;
string RoomDescription;
vector <Door> Doors;
vector <Item> Items;
Room.cpp has things that defined default and overloaded rooms and gave rooms some items and also has these:
vector<Item>Room::GetItems()
{
return Items;
}
int Room::GetItemAmount()
{
return Items.size();
}
main.cpp has some push.backs and stuff and it appears that the items are properly contained in the vector. Now i'm not sure how to print the getter for it it... trying this:
Room FunStoneRoom = Room();
FunStoneRoom.AddItem(ItemCharcoal);
for (unsigned int VectorPos = 0; VectorPos < FunStoneRoom.GetItemAmount(); VectorPos++)
{
cout << FunStoneRoom.GetItems[VectorPos] << " ";
}
cout << endl;
This gives me an error :
Severity Code Description Project File Line Suppression State
Error C3867 'Room::GetItems': non-standard syntax; use '&' to create a pointer to member ConsoleApplication25 d:\tiltan\visual studio\ownclasses\room+item+door\consoleapplication25\main.cpp 51
I also tried:
for (unsigned int VectorPos = 0; VectorPos < FunStoneRoom.GetItemAmount(); VectorPos++)
{
FunStoneRoom.GetItems()[VectorPos];
}
cout << endl;
which doesn't give an error but just prints an empty line.
and:
for (unsigned int VectorPos = 0; VectorPos < FunStoneRoom.GetItemAmount(); VectorPos++)
{
cout << FunStoneRoom.GetItems()[VectorPos];
}
cout << endl;
which marks my << with a red line and tells me no operator "<<" matches these operands...
How do i go about this?
I'm really not that advanced and don't know a lot of complicated functions and codes and whatnot so please try to be as simple as u can with me.
i'm also new here so sorry if i'm not posting or explaining myself properly...
EDIT: per requested - i'm adding item.h and item.cpp but remember i don't need to know what they contain, only a list of the items in the vector:
item.h:
#pragma once
#include <string>
#include <iostream>
using namespace std;
class Item
{
public:
///constructors
Item(); //default item
///overloadeds
//overloaded customizable items
// #param string = Item Name
// #param string = Item Description
Item(string, string);
///destructors
~Item();
///methods
//Display item name and description
void ViewItem();
//Set a new Item Description
void SetItemDescription(string);
//Set a new Item Name
void SetItemName(string);
//Get an Item's name
string GetItemName();
//Get an Item's description
string GetItemDescription();
private:
///properties
string ItemName;
string ItemDescription;
};
item.cpp:
#include "Item.h"
Item::Item()
{
Item::ItemName = "Non Material Item";
Item::ItemDescription = "You cannot see, feel, taste, smell or hear this item";
}
Item::Item(string NewItemName, string NewItemDesc)
{
NewItemName[0] = toupper(NewItemName[0]);
Item::ItemName = NewItemName;
Item::ItemDescription = NewItemDesc;
}
Item::~Item()
{
}
void Item::ViewItem()
{
cout << ItemName << endl;
cout << ItemDescription << endl;
}
void Item::SetItemDescription(string NewItemDescription)
{
if (NewItemDescription.length() < 100)
{
NewItemDescription[0] = toupper(NewItemDescription[0]);
ItemDescription = NewItemDescription;
}
else
{
ItemDescription = "This Item's description is too long";
}
}
void Item::SetItemName(string NewItemName)
{
if (NewItemName.length() < 30)
{
NewItemName[0] = toupper(NewItemName[0]);
ItemName = NewItemName;
}
else
{
ItemDescription = "This Item's name is too long";
}
}
string Item::GetItemName()
{
return ItemName;
}
string Item::GetItemDescription()
{
return ItemDescription;
}
With your first concern, which I quote here ....
Room FunStoneRoom = Room();
FunStoneRoom.AddItem(ItemCharcoal);
for (unsigned int VectorPos = 0; VectorPos < FunStoneRoom.GetItemAmount(); VectorPos++)
{
cout << FunStoneRoom.GetItems[VectorPos] << " ";
}
cout << endl;
This gives me an error : Severity Code Description Project File Line Suppression State Error C3867 'Room::GetItems': non-standard syntax; use '&' to create a pointer to member ConsoleApplication25 d:\tiltan\visual studio\ownclasses\room+item+door\consoleapplication25\main.cpp 51
In this case, the cause is a missing () on the call of GetItems. The compiler is treating this as an attempt to get a pointer to the member function Room::GetItems (since similar syntax, when applied to non-member functions, converts the name of a function into a pointer to that function). That is an error, since pointers to member function are not obtained that way.
With your second concern, which I quote here
I also tried:
for (unsigned int VectorPos = 0; VectorPos < FunStoneRoom.GetItemAmount(); VectorPos++)
{
FunStoneRoom.GetItems()[VectorPos];
}
cout << endl;
which doesn't give an error but just prints an empty line.
In this case, the behaviour you see is correct. In the loop, you have removed the cout <<, but are still surprised that it is producing no output. Room::GetItems() does not produce output - it returns a std::vector<Item>. Retrieving an element from a vector, using operator[](), obtains a reference to the corresponding Item, so also does not produce output.
and:
for (unsigned int VectorPos = 0; VectorPos < FunStoneRoom.GetItemAmount(); VectorPos++)
{
cout << FunStoneRoom.GetItems()[VectorPos];
}
cout << endl;
which marks my << with a red line and tells me no operator "<<" matches these > operands...
The code here is the same as the previous lot, except you have re-inserted the cout << in the loop. That causes the compiler to try to find and call an operator<<() function for writing an Item to an output stream. Your code does not declare such a function, so the compiler cannot find it.
You need to create such a function. It needs to be declared in item.h and defined (implemented) in item.cpp. Those files contain no such declarations.
Now we come to your plea for help (which I've already given you).
How do i go about this? I'm really not that advanced and don't know a lot of complicated functions and codes and whatnot so please try to be as simple as u can with me.
I'm going to be blunt. You are the cause of your own problems here.
Firstly, you are not putting enough effort into interpreting what the compiler is trying to tell you. Compilers are ignorant pieces of software but, in their ignorance, they complain fairly consistently about particular types of error. So you need to apply effort into understanding your compiler's error messages. If you don't, you'll never be able to fix your own code when a compiler rejects it.
Then you are compounding your problems by randomly changing code in the hope of fixing it, rather than making reasoned changes. The result of that is either behaviour your don't understand (if the code compiles and runs) or error messages from your compiler that you won't understand, unless you understand the change you actually made.
When you are dealing with a confirmed ignoramus (the compiler) you cannot afford to be ignorant.
A sample example is -
#include <iostream>
using namespace std;
class Item
{
int id;
string description;
public:
Item(int id,string description)
{
this->id=id;
this->description=description;
}
friend ostream& operator<<(ostream& os, const Item& it);
};
ostream& operator<<(ostream& os, const Item& it)
{
os << "Id : " << it.id << " Description : " <<it.description<<endl;
return os;
}
int main()
{
Item it(5, " calculator");
cout << it;
}

List Insert STL

I don't understand why my code doesn't insert to the list.
But if I change the line where I use the insert by doing a push_back the element is inserted to the list. Thank you
But I have to have it sorted. The operator < is well implemented:
void Movies::afegirPeliculaDirector(string director,string title,int year){
list<actorDirectorMovie> llista;
actorDirectorMovie dir(title,year);
int total=_mapDirectors.count(director);
if (total>0){
map<string,list<actorDirectorMovie> >::iterator
it=_mapDirectors.find(director);
llista=(*it).second;
list<actorDirectorMovie>::iterator itList=(*it).second.begin();
while(itList!=(*it).second.end() and (*itList) < dir){
itList++;
}
if (itList==(*it).second.end()) llista.push_back(dir);
else {
cout << llista.size() << endl;
llista.insert(itList,dir);//->>>>>>>>>>>>>>>>>>>> IT DOESN'T INSERT, WHY?
cout << llista.size() << endl;
}
it->second=llista;
}
else {
llista.push_back(dir);
_mapDirectors.insert(make_pair(director,llista));
}
directorMovies(director);
}
Your itList iterator refers to a different container. itList points to a member of _mapDirectors[director].second but you're trying to use it as an insertion point into llista.
I think the problem is that you wanted llista to be a reference to the mapped list, but instead you're making a copy of it.
Try the following code (I haven't tested it but it should give you the idea). Note that it takes a reference to the mapped list. There's also no need to test for an empty map, or do an explicit find for the director - you can simply reference _mapDirectors[director].second and the empty list will be created automatically if it's not already in the map.
void Movies::afegirPeliculaDirector(string director,string title,int year)
{
// get a reference to the director's list
list<actorDirectorMovie>& llista = _mapDirectors[director];
actorDirectorMovie dir(title,year);
list<actorDirectorMovie>::iterator itList=llista.begin();
while(itList!=llista.end() and (*itList) < dir){
itList++;
}
if (itList==llista.end()) llista.push_back(dir);
else {
cout << llista.size() << endl;
llista.insert(itList,dir);
cout << llista.size() << endl;
}
}
You could also consider changing from using a list to store each director's movies to a set, as this has the property of being sorted automatically for you. The whole function would be reduced to _mapDirectors[director].insert(dir) in that case.

C++: Tree node not updating

I am trying to update a node with a new value, but when I print out the node in another function, the old value is being displayed. I have also tried setting 'question' to the return value of updateTree(), in which it would return the new updated node, but that yields the same result.
void f(Node *n){//n is a pointer that has a string value with a left and right pointer. lets say that "n" right now is "duck"
//do stuff....
updateTree(n);
cout << n->value;//prints out "duck" rather than the updated value..
}
void updateTree(Node *question){
string animal, q;
cout << "Darn, I lost. What was is? ";
getline(cin, animal);
cout << "Enter a question that is true for a(n) " << animal << " and false for a(n) " << question->value << ": ";
getline(cin, q);
Node right(question->value, nullptr, nullptr);//the old animal ie "duck"
Node left(animal, nullptr, nullptr);//the new animal
question = new Node(q, &left, &right);//updated "n" ie "duck" to something else
}
Your code
void updateTree(Node *question) {
// ^^^^^^ That's a copy of the pointer variable passed.
// Assignments will never affect the original pointer value
// ...
question = new Node(q, &left, &right);
}
sends the newly created Node to void, it's lost as soon that function leaves scope. You're operating on a copy of that pointer variable.
What you actually need is a reference that allows changing the original pointer:
void updateTree(Node*& question) {
// ^