storing an object name during construction of another object - c++

I wanted to create objects from the class “takeSnapshots” that would learn, upon their instantiation, the name of another object from the class “lock” that they could query later as the state of the “lock” object changes. I can think of multiple ways of letting the object from class “takeSnapshots” know which object it is to query (like including the name of the “lock” object as part of the call to its member functions). But, I thought it better to take care of the relation in the beginning and not worry later if I am calling the correct object combinations.
The included code shows stripped down versions of the two classes and example instantiations created in main.
I have included the outputs on each line following their respective couts.
What I expected was that the constructor of “takeSnapshots” would store away the address of the “lock” object. Then I could use it later when taking a snapshot. You can see that what gets stored away (at least when I use it to get numWheels) is a few addresses off from the address that the “lock” object thinks it has for numWheels.
I am mostly interested in knowing why this code does not work the way I expect, i.e, if this is not a good architectural idea, that is one thing. But with the behavior I’m seeing here, I’m clearly not ready to use pointers in anything complicated and I don’t want to give up on the basic architecture just because of erroneous implementation. Any help would be greatly appreciated.
// simpleTest.cpp : Demonstrates problem I'm having understanding
// pointer to an object.
#include "stdafx.h"
#include<iostream>
using namespace std;
class lock {
public: //Just while I run a test.
int numWheels;
lock(int numW) {
numWheels = numW;
cout << " \n In \"lock\" constuctor, address and value of numWheels
" << &numWheels << " " << numWheels << endl;
} //Values from console: 0034F874 and 4
};
class takeSnapshots {
lock* localLock;
public:
takeSnapshots(lock myLock) {
localLock = &myLock;
cout << " \n In \"takeSnapshots\" constuctor, address and value of
numWheels " << &localLock->numWheels << " "
<< localLock->numWheels << endl;
//Values from console: 0034F794 and 4 "Same value, but not the same
//address as expected from "lock."
}
void takeASnapSnapshot() {
cout << " \n When taking a snapshot, address and value of numWheels
" << &localLock->numWheels << " " << localLock->numWheels <<
endl;
//Values from console: 0034F794 and 2303449 "No longer even the
// same value as expected from "lock."
}
};
int main()
{
lock yourLock(4);
takeSnapshots myShots1(yourLock);
cout << " \n In main (from \"yourLock\"), address and value of
numWheels " << &yourLock.numWheels << " " << yourLock.numWheels <<
endl;
//Values from console: 0034F874 and 4 "Still the same values as set
//in the constructor of "lock."
//Take a picture
myShots1.takeASnapSnapshot();
return 0;
}

Related

object empty inside calling function using pointer as argument

I am learning C++ with pointers and trying to program a small game. I have a class PlayerManager which should create players and save them in a file.
The code compiles but when I call the method savePlayer, the pointer inside the method is valid but I cannot access the object to which the pointer is pointing.
I have searched for similar problems on internet but did not find anything similar. I may not be looking for the right keywords as I have no idea where this comes from.
I checked before the function is called and the pointer is working and I can access the object.
Inside the calling function, the pointer still has the right address but I cannot access the object. Nothing is returned.
After the calling function the pointer is still valid and the object accessible. (see //Comments in the code below)
Here are my two functions inside my PlayerManager class.
void PlayerManager::createPlayer()
{
Player *playerPtr = new Player();
std::string name;
std::cout << "Name: ";
std::cin >> name; // I entered for instance John
std::cout << std::endl;
playerPtr->setName(name);
std::cout << "PlayerPtr name before savePlayer: " << playerPtr->getName() << std::endl; // Outputs John
std::cout << "playerPtr before savePlayer: " << playerPtr << std::endl; // Ouputs the address
this->savePlayer(playerPtr);
std::cout << "PlayerPtr name after savePlayer but inside createPlayer: " << playerPtr->getName() << std::endl; // Outputs: John
delete playerPtr;
}
void PlayerManager::savePlayer(Player* playerPtr) // the called method
{
std::cout << "playerPtr inside savePlayer: " << playerPtr << std::endl; // Outputs the address
std::cout << "PlayerPtr name inside savePlayer: " << playerPtr->getName() << std::endl; // Outputs nothing
std::string const fileName = "Players/"+playerPtr->getName()+".txt";
std::cout << fileName << std::endl; // Outputs Players/.txt
std::ofstream myFile = std::ofstream(fileName.c_str());
if(myFile)
{
std::cout << "Enregistrement du nouveau joueur." << std::endl; // The code launches but no file is created.
myFile << "{"<< std::endl;
myFile << "name: " + playerPtr->getName() <<std::endl;
} else {
std::cout << "Erreur d'enregistrement du fichier." << std::endl;
}
}
I would like to be able to access the object created in createPlayer method inside the savePlayer method by passing a pointer but I just get an empty string for
playerPtr->getName()
I don't understand how the object is accessible before the call of the method and after but not inside as the address is still valid.
EDIT1
Thank you for guiding me to the obvious mistake !
Because of recuring crash of code:blocks my getName() method was deleted before I could save it and I did not think about checking it. By writing the following getName() it worked:
std::string Player::getName() const
{
return m_name;
}
Yet I do not understand why and How I got an output in createPlayer() although the method getName() was empty. Is this normal ?
EDIT 2
I'll create a new question for this strange behavior.
The code you have should work fine. My only guess is that there's something fishy about your getter function getName().
I presume you have something along these lines?
const std::string &getName() const
{
return name;
}
Online code example: https://rextester.com/INHG32142

Struggling with pointers to Assign new contents to a vector

Okay so what I am trying to do is add an instance of a class to a specific index of a vector. This index can either be initially non-existent, or be an existing index which has been cleared and is having a new class instance being written to that position.
Below is the function that I have been using to try and write these instances to the vector, and commented at the bottom you can see the other 2 methods that I tried to use, Obviously with push_back only being able to add new vectors at the end.
I have a feeling that assign may only be able to add data to existing elements? And that insert may add a new element and shift the existing elements down instead of overwriting. Just want a bit of clarity on this, as the C++ tutorials have started confusing me.
Also, what would be the correct way to reference/defreference/call the Person vector (in this case being referred to as "allthePeople"), so that it is possible to change its data?
void createnewPerson(int assignID, RECT startingpoint, vector<Person>* allthePeople, int framenumber) {
Person newguy(assignID, startingpoint, framenumber);
std::cout << "New Person ID number: " << newguy.getIDnumber() << std::endl;
std::cout << "New Person Recent Frame: " << newguy.getlastframeseen() << std::endl;
std::cout << "New Person Recent history bottom: " << newguy.getrecenthistory().bottom << std::endl;
int place = assignID - 1;
//This is where I am confused about referencing/dereferencing
allthePeople->assign(allthePeople->begin() + place, newguy);
//allthePeople->insert(place, newguy);
//allthePeople->push_back(newguy);
}
Also just to clarify, "place" is always 1 less than "assignID", because vector positions start at 0, and I simply wanted to start their ID numbers at 1 instead of 0.
-------------EDIT : ADDED IF LOOP THAT SOLVED PROBLEM-----------------
void createnewPerson(int assignID, RECT startingpoint, vector<Person>* allthePeople, int framenumber) {
Person newguy(assignID, startingpoint, framenumber);
std::cout << "New Person ID number: " << newguy.getIDnumber() << std::endl;
std::cout << "New Person Recent Frame: " << newguy.getlastframeseen() << std::endl;
std::cout << "New Person Recent history bottom: " << newguy.getrecenthistory().bottom << std::endl;
int place = assignID - 1;
if (allthePeople->size() > place)
{
//assuming places starts from 1 to vector's size.
(*allthePeople)[place] = newguy;
}
else
{
allthePeople->push_back(newguy);
}
}
assign is meant to replace the full content of a vector.
Assuming that you want to put every person in a specific place. You might then better use operator[] to put the value at the place you want instead of using assign. You need to have the vector with the appropriate size.
if (allthePeople->size() >= place )
{
//assuming places starts from 1 to vector's size.
(*allthePeople)[place - 1] = newguy;
}

Allocating Dynamic Memory to PlayerID

For hours now I've been trying to work out to how I can assign dynamic memory to a certain playerid, when they join a server, and destroy it when they leave.
I've tried numerous things, I've tried making an array of pointers... which would allow me to access the information with the player ID using the pointer and array position:
int *pInfo[MAX_PLAYERS]; // Global
//Function Local
CPlayers p;
pInfo[playerid] = p;
Which doesn't work, it tells me it cannot convert the class initialisation to a memory pointer.
I tried the same thing, with this line instead:
std::unique_ptr<CPlayers> pInfo[playerid];
However it needs a constant expression where playerid is, this means I cannot do this unless I know what the player ID is and enter it directly... which is impossible as I won't know until they client tries to connect.
Does anyone have a solution that will allow me to make memory dynamically, and have this memory accessible via the playerid. Or some other fashion, that me indefinitely use that clients information in game.
As I have ran out of ideas... I can't find anything online. I'm new as well so there may be functions I've over looked.
Thanks.
You can use MAP container to do that. The ideia is that you have 2 values. The first one is the playerID and the second one, a dynamic memory reference, which contains its properties. Following is a simple example to prove the concept.
#include <map>
#include <memory>
#include <iostream>
int main()
{
std::map<int, std::unique_ptr<int>> pinfo;
// Inserting some elements.
pinfo.emplace(1, std::unique_ptr<int>(new int{3}));
pinfo.emplace(800, std::unique_ptr<int>(new int{700}));
for (auto& i: pinfo)
std::cout << "Player " << i.first << ", value " << *i.second.get() << std::endl;
// Deleting. Note that, due unique_ptr, the memory is deallocated automatically
pinfo.erase(1);
std::cout << "Player 1: deleted" << std::endl;
for (auto& i: pinfo)
std::cout << "Player " << i.first << ", value " << *i.second.get() << std::endl;
}

C++ Array passed by reference, but how to understand this?

The arrays are passed by reference. Any changes made to the array within the function changeArray will be observed in the calling scope (main function here).
However the codes below print 0 1 in the 1st cout, and print 2 in the 2nd "cout". What I don't understand is that why the first cout prints the original value of array[0]=1 instead of the changed value of array[0]=2?
Thanks a lot.
#include <iostream>
using namespace std;
int changeArray(int array[]) {
array[0]=2*array[0];
return 0;
}
int main() {
int array[]={1,2,3,4};
cout << changeArray(array) << " " << array[0] << endl;
cout << array[0] << endl;
return 0;
}
To make sure that the compiler doesn't reorder the execution:
cout << array[0] << endl;
changeArray(array);
cout << array[0] << endl;
This prints 1 and then 2.
The C++ compiler is allowed to optimize the code by reordering the execution of code within a single expression (e.g. cout << changeArray(array) << " " << array[0] << endl). To avoid that, and to make sure changeArray gets called first, you need to split your expression to separate statements, e.g. by using the semicolon (;). Everything before the semicolon gets executed before anything after the semicolon can start.

TOUGH: Dealing with deeply nested pointers in C++

I define this structure:
struct s_molecule
{
std::string res_name;
std::vector<t_particle> my_particles;
std::vector<t_bond> my_bonds;
std::vector<t_angle> my_angles;
std::vector<t_dihedral> my_dihedrals;
s_molecule& operator=(const s_molecule &to_assign)
{
res_name = to_assign.res_name;
my_particles = to_assign.my_particles;
my_bonds = to_assign.my_bonds;
my_angles = to_assign.my_angles;
my_dihedrals = to_assign.my_dihedrals;
return *this;
}
};
and these structures:
typedef struct s_particle
{
t_coordinates position;
double charge;
double mass;
std::string name;
std::vector<t_lj_param>::iterator my_particle_kind_iter;
s_particle& operator=(const s_particle &to_assign)
{
position = to_assign.position;
charge = to_assign.charge;
mass = to_assign.mass;
name = to_assign.name;
my_particle_kind_iter = to_assign.my_particle_kind_iter;
return *this;
}
} t_particle;
struct s_bond
{
t_particle * particle_1;
t_particle * particle_2;
std::vector<t_bond_param>::iterator my_bond_kind_iter;
s_bond& operator=(const s_bond &to_assign)
{
particle_1 = to_assign.particle_1;
particle_2 = to_assign.particle_2;
my_bond_kind_iter = to_assign.my_bond_kind_iter;
return *this;
}
};
and then in my code I return a pointer to an s_molecule (typedef'd to t_molecule, but still).
Using this pointer I can get this code to work:
for (unsigned int i = 0;
i < current_molecule->my_particles.size();
i++)
{
std::cout << "Particle "
<< current_molecule->my_particles[i].name << std::endl
<< "Charge: "
<< current_molecule->my_particles[i].charge << std::endl
<< "Mass: "
<< current_molecule->my_particles[i].mass << std::endl
<< "Particle Kind Name: "
<< (*current_molecule->my_particles[i].my_particle_kind_iter).atom_kind_name
<< std::endl
<< "x: " << current_molecule->my_particles[i].position.x
<< " y: " << current_molecule->my_particles[i].position.y
#ifdef USE_3D_GEOM
<< "z: " << current_molecule->my_particles[i].position.z
#endif
<< std::endl;
}
If I replace it with:
for (std::vector<t_particle>::iterator it = current_molecule->my_particles.begin();
it !=current_molecule->my_particles.end();
it++)
{
std::cout << "Particle "
<< (*it).name << std::endl
<< "Charge: "
<< (*it).charge << std::endl
<< "Mass: "
<< (*it).mass << std::endl
<< "Particle Kind Name: "
<< (*(*it).my_particle_kind_iter).atom_kind_name
<< std::endl
<< "x: " << (*it).position.x
<< " y: " << (*it).position.y
#ifdef USE_3D_GEOM
<< "z: " << (*it).position.z
#endif
<< std::endl;
}
I now get nasty segfaults...
Not to put too much here, but I'm also getting segfaults when I tried to do this:
std::cout << "Bond ATOMS : "
<< (*current_molecule).my_bonds[0].particle_1->name
<< std::endl
Again, current_molecule is a pointer to a s_molecule structure, which contains arrays of structures, which in turn either directly have vars or are pointers. I can't get these multiple layers of indirection to work. Suggestions on fixing these segfaults.
FYI I'm compiling on Linux Centos 5.4 with g++ and using a custom makefile system.
#sbi Thanks for the good advice! I believe you are right -- the assignment overloaded operator is unnecessary and should be scrapped.
I've followed the approach of commenting out stuff and am very confused. Basically in the function that passes the pointer to my particular molecule to the main function to print, I can see all the data in that molecule (bonds, particles, name, etc) perfectly, printing with cout's.
Once I pass it to the main as a ptr, if I use that ptr with an iterator I get a segfault. In other words. Also for some reason the bond data (which I can freely print in my funct that returns to the pointer) also segfaults if I try to print it, even if I use the [] to index the vector of bonds (which works for the particle vector).
That's the best info I can give for now.
A wild guess: Are you using shared libraries. I remember having difficulties passing STL-containers back and forth across shared library boundaries.
Jason (OP) was asked in a comment by David Rodríguez:
Are you returning a pointer to a local variable?
Jason answered:
No its a ptr to a class variable. The class is very much in existence (it contains the function that returns the molecule).
Unless you're talking of a true class variable (qualified as static), the fact that the class exists doesn't have much to do with it. Instances of a class exist, and they might have ceased to exist even if you just called a function on them.
As such, the question is:
Does the instance of the class that returned the pointer current_molecule still exist?
Or is current_molecule qualified as static, i.e. being a true class variable?
If the answer to both questions is "no", you're in Undefined County.
At this point, it becomes very important that you post source code that can be used by us here to actually reproduce the problem; it might well be located in source you aren't showing us.
Again, this issue was answered here:
Weird Pointer issue in C++
by DeadMG. Sorry for the double post.