Having trouble with manipulating a vector within a class - c++
I need to define a vector of testmodes that I can then manipulate the values of through various methods.
Here is how I define the TestMode class:
class TestMode{
public:
TestMode(int val, int jamramaddr){
value=val;
jamramaddress=jamramaddr;
}
int getAddr(void){
return jamramaddress;
}
void setValue(int val){
value=val;
}
int getValue(void){
return value;
}
private:
int value;
int jamramaddress;
};
Pretty simple.
I then have a TestModeGroup class to perform actions on the vector of testmodes that I have created. That class looks like this:
class TestModeGroup{
public:
TestModeGroup(const std::vector<TestMode> &TestModes){
TestModeVector=TestModes;
}
//Compare the given jamramaddress against the known jamramaddress of the given testmode. If it is a match then update the testmode value
void compareAndStore(TestMode &TM){
int TM_address=TM.getAddr();
if(TM_address==JamRamAddress){
output("Match found! Old TM value %d", TM.getValue());
TM.setValue(JamRamData);
output("New TM value %d", TM.getValue());
}
}
//Commit the given testmode to the jamram with the latest known value
void writeTmBitToJamRam(TestMode &TM){
JamRamAddress=TM.getAddr();
JamRamData=TM.getValue();
apg_jam_ram_set(JamRamAddress,JamRamData);
}
//running TestModeGroupObject.store(address, data) will find which test mode that jamram address is for and set the appropriate test mode value for later printing.
//This is meant to be used in conjuction with the Excel spreadsheet method of entering test modes
void store(int address, int data){
JamRamAddress= address;
JamRamData = data;
output("Current JamRamAddress = %d JamRamData = %d", JamRamAddress, JamRamData);
apg_jam_ram_set(JamRamAddress,JamRamData);
for(std::vector<TestMode>::iterator it = TestModeVector.begin(); it!=TestModeVector.end(); ++it){
compareAndStore(*it);
}
}
//Running TestModeGroupObject.load() will commit all test mode changes to the jamram for test modes that are part of that object
void load(void){
for(std::vector<TestMode>::iterator it = TestModeVector.begin(); it!=TestModeVector.end(); ++it){
writeTmBitToJamRam(*it);
}
}
int getTMVal(TestMode &TM){
return TM.getValue();
}
private:
int JamRamAddress;
int JamRamData;
std::vector<TestMode> TestModeVector;
};
Here's how I defined the vector:
TestMode adm_testmodes[] = {TM_TWINWL,TM_TWINBL,ON_2WL,ON_2BL,WV_S1X,WV_S0X,TM_PCHG_RH_3,TM_PCHG_RH_2,TM_PCHG_RH_1,TM_PCHG_RH_0,TM_PCHG_RH_BYP,TM_PCHG_SF_3,TM_PCHG_SF_2,TM_PCHG_SF_1,TM_PCHG_SF_0,TM_PCHG_SF_BYP,
TM_PCHG_V04_3,TM_PCHG_V04_2,TM_PCHG_V04_1,TM_PCHG_V04_0,TM_PCHG_V04_BYP,TM_SA_DIS,TM_TS_NEGSLOPE,TM_TRIM_4,TM_TRIM_3,TM_TRIM_2,TM_TRIM_1,TM_TRIM_0,TM_TSSLP_2,TM_TSSLP_1,TM_TSSLP_0,
TM_WRV_N_2,TM_WRV_N_1,TM_WRV_N_0,TM_SAGAIN_EN,TM_REFTRIM_EN,TM_READ_DONE_OPT_EN,EnableCore_Read,SA_4,TM_OC_2,TM_OC_1,TM_OC_0,TM_WRLC_4,TM_WRLC_3,TM_WRLC_2,TM_WRLC_1,TM_WRLC_0,
TM_WRHC_4,TM_WRHC_3,TM_WRHC_2,TM_WRHC_1,TM_WRHC_0,TM_FTOP_3,TM_FTOP_2,TM_FTOP_1,TM_FTOP_0,TM_RISE_1,TM_RISE_0,TM_WRH_3,TM_WRH_2,TM_WRH_1,TM_WRH_0,TM_SET_4,TM_SET_3,TM_SET_2,TM_SET_1,TM_SET_0,
TM_REFSTART,TM_REFSEL_1,TM_REFSEL_0,TM_REFSL_5,TM_REFSL_4,TM_REFSL_3,TM_REFSL_2,TM_REFSL_1,TM_REFSL_0,TM_REFSH_5,TM_REFSH_4,TM_REFSH_3,TM_REFSH_2,TM_REFSH_1,TM_REFSH_0,TM_READ_DONE_ADD,
TM_READ_DONE_OPT,TM_READ_DONE_5,TM_READ_DONE_4,TM_READ_DONE_3,TM_SAGAIN_1,TM_SAGAIN_0,TM_REFR_5,TM_REFR_4,TM_REFR_3,TM_REFR_2,TM_REFR_1,TM_REFR_0
};
std::vector<TestMode> ADM_TMs (adm_testmodes, adm_testmodes + sizeof(adm_testmodes) / sizeof(TestMode));
TestModeGroup ADM_TestModeGroup(ADM_TMs);
So far so good. I can directly access all of the TestModes that are defined, change the value and have that change persist everywhere. The problem comes when I try to run the "store" function within the TestModeGroup class. It seems that I have a local copy of the TestModes that gets updated, but not the original TestMode. I'm sure that this is a pretty simple problem but I'm struggling. C++ is not my specialty, and OOP even less so.
Here's a quick example for a dummy testmode I created:
output("DUMMY_TESTMODE Initial Value: %d", DUMMY_ADM_TestModeGroup.getTMVal(DUMMY_TESTMODE));
DUMMY_TESTMODE.setValue(1);
output("DUMMY_TESTMODE Set to 1 Value: %d", DUMMY_ADM_TestModeGroup.getTMVal(DUMMY_TESTMODE));
DUMMY_TESTMODE.setValue(0);
output("DUMMY_TESTMODE Set to 0 Value: %d", DUMMY_ADM_TestModeGroup.getTMVal(DUMMY_TESTMODE));
DUMMY_ADM_TestModeGroup.store(22,1);
output("DUMMY_TESTMODE Set to 1 Value: %d", DUMMY_ADM_TestModeGroup.getTMVal(DUMMY_TESTMODE));
doing the .setValue works fine, but doing the .store does not. When I print out the value it comes back as 0. Within the .store function I do a printout, though, and that gives the right value of 1. Somehow I think I am simply altering a copy of the original vector, but I just can't figure it out. I've been driving myself crazy and nobody I've talked to knows enough about C++ to help. Does anybody have any insight as to where I've screwed up?
Try changing TestModeGroup class:
class TestModeGroup{
public:
TestModeGroup(const std::vector<TestMode> &TestModes) : TestModeVector(TestModes)
{}
// ...
std::vector<TestMode> & TestModeVector;
};
If you want vector modifications done inside class to be applied to the original value passed to the constructor, you need to store a reference to the original object. Let me know if this helped :)
Related
Pointer gives abnormal values after deferencing
I am trying to replicate a big C++ library. It has the following structure of code RobotRunner.h class RobotRunner { public: VectorNavData* vectorNavData; }; RobotRunner.cpp void RobotRunner::run() { printf("Quaternion[0]: %f \n", vectorNavData->quat[0]); //Output: 243235653487854 - Abnormal values } SimulationBridge.h class SimulationBridge { private: VectorNavData _vectorNavData; // Actual value of vectornavdata from the robot is stored here RobotRunner* _robotRunner = nullptr; //Pointer to the RobotRunner Object } SimulationBridge.cpp void SimulationBridge::init() { _robotRunner = new RobotRunner(); printf("Quaternion[0]: %f \n", _vectorNavData.quat[0]); // Output: 0.43 - Normal and expected _robotRunner->vectorNavData = &_vectorNavData; } void SimulationBridge::run() { _robotRunner->run(); } //This function runs continuously and updates the _vectorNavData in a separate thread void SimulationBridge::readIMU() { while(true) { //_lowState stores the values of different robot parameters at a given time _vectorNavData.accelerometer[0] = _lowState.imu.accelerometer[0]; _vectorNavData.accelerometer[1] = _lowState.imu.accelerometer[1]; _vectorNavData.accelerometer[2] = _lowState.imu.accelerometer[2]; _vectorNavData.quat[0] = _lowState.imu.quaternion[1]; _vectorNavData.quat[1] = _lowState.imu.quaternion[2]; _vectorNavData.quat[2] = _lowState.imu.quaternion[3]; _vectorNavData.quat[3] = _lowState.imu.quaternion[0]; _vectorNavData.gyro[0] = _lowState.imu.gyroscope[0]; _vectorNavData.gyro[1] = _lowState.imu.gyroscope[1]; _vectorNavData.gyro[2] = _lowState.imu.gyroscope[2]; } } VectorNavData is a struct which stores the details about the orientation of the robot. It has the following definition struct VectorNavData { Vec3<float> accelerometer; Vec3<float> gyro; Quat<float> quat; }; I have included only the necessary part of the code here for brevity. Code Explanation: SimulationBridge class communicates with the robot in the simulation. It takes in vectorNavData and stores it in the member variable _vectorNavData. SimulationBridge also contains the pointer to the RobotRunner class as one of it's member. I am allocating the address of _vectorNavData object to the pointer _robotRunner->vectorNavData (check SimulationBridge.cpp). Inside the RobotRunner class I deference this pointer and use the values in other parts of the code. Problem: If I print the vectorNavData inside the SimulationBridge.cpp the values seems to be normal. But after assigning the pointer of the same object to the robot runner, if I print the values there the values seems to be abnormally high. My question is, is this way of using pointers for dynamic allocation recommended? If not what is the best alternative way I can use? Another important point to note is, I am compiling the code with CMake and "-O3" optimization flag is set to the CMAKE_CXX_FLAGS. If I remove this flag, the code sorta works fine for the above object pointer but I am still getting similar error for another object pointer in another part of the code. I have not included that here because it's pretty complex to describe the code structure and the problem essentially is the same.
GMock: How to return mock class variable as the return value
I am trying to use GMock (google mocking framework for c++) for the first time. I have the following class: class LocalCache { public: virtual time_t GetCurrentTime() = 0; virtual int AddEntry(const std::string key, std::string& value); virtual int GetEntry(const std::string key, std::string& value); }; The GetEntry method invokes GetCurrentTime call. I'd like to mock the GetCurrentTime method so that I can advance the clock in my test to test the aging out of entries which happens as part of the GetEntry call (please don't ask me why the aging is being done as part of GetEntry call... that's another discussion :( ). Here's my mock class: class MockLocalCache : public LocalCache { public: using LocalCache::GetCurrentTime; MOCK_METHOD0(GetCurrentTime, time_t()); MockLocalCache() : mCurrentTime(0) { } void EnableFakeTime() { ON_CALL(*this, GetCurrentTime()).WillByDefault(Return(mCurrentTime)); } void SetTime(time_t now) { mCurrentTime = now; } private: time_t mCurrentTime; }; TEST(MockTest, TimeTest) { MockLocalCache mockCache; mockCache.EnableFakeTime(); std::string key("mykey"); std::string value("My Value"); EXPECT_TRUE(mockCache.AddEntry(key, value)); mockCache.SetTime(10); // advance 10 seconds std::string expected; EXPECT_TRUE(mockCache.GetEntry(key, expected)); } When I run the test, I expected the mCurrentTime value to be return by my mock GetCurrentTime function. However, I get the following error output: GMOCK WARNING: Uninteresting mock function call - taking default action specified at: ..../test_local_cache.cpp:62: Function call: GetCurrentTime() Returns: 0 Stack trace: Would appreciate it if someone can let me know what I am doing wrong and how to fix it. Thanks in advance.
The solution to your problem is to make it in much simpler way. Just use EXPECT_CALLwhere you expect call to your mocked function: class MockLocalCache : public LocalCache { public: MOCK_METHOD0(GetCurrentTime, time_t()); }; TEST(MockTest, TimeTest) { MockLocalCache mockCache; std::string key("mykey"); std::string value("My Value"); EXPECT_TRUE(mockCache.AddEntry(key, value)); EXPECT_CALL(mockCache, GetCurrentTime()).WillOnce(Return(10)); // advance 10 seconds std::string expected; EXPECT_TRUE(mockCache.GetEntry(key, expected)); } Just to answer why your example did not work - with this call, the current value of your member variable is stored - later change to it has no effect: ON_CALL(*this, GetCurrentTime()).WillByDefault(Return(mCurrentTime)); Look in google-mock-doc for difference between Return and Return(ByRef... Probably - I did not check this, calling set member value, before calling setting this default would also work - but as I said - for your case EXPECT_CALL shall be used: mockCache.SetTime(10); // advance 10 seconds mockCache.EnableFakeTime();
Just for the record (and future people finding this question, like me), while PiotrNycz's answer is the best option when you can do it (keeping test values directly within tests) -- in some cases it really is necessary to return a "live" return value from a field or variable. The appropriate documentation is here; in particular: Return(field) doesn't work (it makes a copy of the field's current value when the action is defined) Return(ByRef(field)) also doesn't work (it does exactly the same as above, contrary to what you might expect) ReturnRef(field) doesn't compile (because the return type isn't a reference) ReturnPointee(&field) does work (it returns the value as of the time the method is actually called) Of course, you have to ensure that the pointee remains valid whenever the method is called, since it's now being used directly instead of making a copy.
Return a pointer from a function to an object initialized in main()
I have been struggling with this problem for a few hours now and I've searched for every term that made sense to me. I might even have already read through a relevant answer but didn't recognize it as such because I'm a little confused by pointers. So, I have a struct that is part of an object which is part of a chain of objects that is "anchored" (if you can call it that) in another object, which is itself part of a chain which is "anchored" in an anchor object initialized in main. struct values { double val, ues; } class small { public: values vals; } class big { public: small *small_anchor; } values &getPointerToStruct(big *con) { values *return_vals; if(con->small_anchor->vals.val==10) return_vals=con->small_anchor->vals; return (&return_vals); } int main() { values *main_values=NULL;//This is supposed to be pointing to the "vals" struct contained inside the "small" object. big *big_anchor; big_anchor = new big; big_anchor->small_anchor = new small; big_anchor->small_anchor->vals.val=10; big_anchor->small_anchor->vals.ues=5; main_values = getPointerToStruct(&big_anchor);//now main_values should be pointing to the "vals" struct //I want to manipulate the value INSIDE the object itself main_values.val++; } I have tried every combination of &, * and no prefix I could come up with, but nothing would give the result I was hoping for. "Closest" I got was copying "vals" (from inside the object) into "main_values" so that I could manipulate the values there, which isn't of any use to me, as I want to manipulate the SOURCE of the variables. Also please note that I left out the process of scrolling down the chains to get to the object I was trying to reach and that "return_vals" seems arbitrary, but it happens that there are two possible candidates that could be the struct my program is looking for and the "return_vals" contains the best candidate found so far and is overwritten when a better one is found, or returned when the routine ends.
You wrote values &getPointerToStruct(big *con) { values *return_vals; if(con->small_anchor->vals.val==10) return_vals=con->small_anchor->vals; return (&return_vals); } where I think you wanted values *getPointerToStruct(big *con) { values *return_vals = 0; if(con->small_anchor->vals.val==10) return_vals=&con->small_anchor->vals; return (return_vals); } But the . in main_values.val++; is wrong anyway. You need to be consistent about whether you wanted to work with a values* or a values&. You could make all this work with a values& if you like, but then main_values should be a values& and not declared until you are ready to initialize it. return_vals would not be practical as a values& because of the stated requirement that the full code gives it a tentative address that is conditionally modified later. But even with return_vals as a values* you could still return a values& if that is what you preferred.
Visual Studio Compiler is highlighting Static variables differently?
I'm programming in C++ and have a method which uses a static variable. The method isn't working as I think it should; upon investigation, I found that my static variable is being highlighted in red in two places and blue in other places. Below is the code: int GameModeState::changeJob(int number) { static int job = 1; //red if (number == 1) { job = (job+1); //First one is red, second one is blue return job; //blue } else { return job; //blue } } I'm calling this method with other methods, one shown for example: int GameModeState::getJob() { int currentJob = (changeJob(2)); return currentJob; } I want a method like getJob() to simply return the current value of job, while another method, when calling changeJob(number) is changeJob(1), to increment job's value by one. (Hence the if/else statement in changeJob(number)). Since the job variables are highlighted differently, I'm thinking the compiler is saying that it views the two separately somehow? I'm getting stuck with job being some even value. EDIT I also have Awesomium... I believe that is the only addition to the compiler, but I'm not completely sure. MOAR EDIT In another class, I have a method which should determine the current job's number and do something based on if the number is even or odd (since right now there are only two jobs) void ZoneMovementState::_changeZone(const String& message, const Awesomium::JSValue& input, Awesomium::JSValue& output) { //Awesomium::JSValue::Object object = input.getObject(); //String zoneFilename = Convert::toString(object[L"zoneFilename"].toString()); // If the number from getJob is even, the player is currently a geologist if (GameModeState::getJob()%2 == 0) { ZoneParser::getSingleton().load("../media/zones/geology_zone.xml", false); } else { ZoneParser::getSingleton().load("../media/zones/farm_zone.xml", false); } transitionHandler->go(); } Ignore the two commented out lines; they deal with JS, which I'm not working on for now. In the program, I can access the farm_zone until I increment job's value using the below method in GameModeState: void GameModeState::_openNotebook(const String& message, const Awesomium::JSValue& input, Awesomium::JSValue& output) { mNotebookTransition->go(); static int currentJob = changeJob(1); } .... So I figured out my problem. While going through the code to show you guys, I realized that the static for currentJob was probably unneeded... once I removed it, my code works as it should now. Thanks for the help guys!
Part of the problem here is you're using a static local for what very likely should just be a member variable. A static local maintains it's value across all calls to a function in all threads in a process. It's much more likely that you want it to persist for all calls to changeJob in a particular GameModeState instance (else why make it a member functon to begin with?). To do this you'll need to define a member variable on GameModeState initialize it in the constructor and then access it in the method. For example class GameModeState { int job; GameModeState() : job(1) {} int changeJob(int number); }; int GameModeState::changeJob(int number) { if (number == 1) { job = (job+1); return job; } else { return job; } } Note: I'm not entirely sure why you're seeing the color's your are seeing. Visual Studio by default won't color member variables a particular color in C++ so it's very likely another add-in you are using.
Nah, highlighting doesn't mean anything. That is, the editor doesn't call the compiler before deciding how/what/when to highlight. So that is not your problem. Sorry 'bout that :-) You can prove this to yourself by going to Tools->Options->TextEditor and noticing that you can change the highlighting by choosing a different text-editing model.
What's a better way to store information than by using static ints? C++
I'm keeping track of a player's "job" by setting his job to a number, and incrementing it by one if he changes job, and determining which job he currently is by whether the number is even or odd. (Only two jobs right now). However, I know there are better ways of doing this, and soon I'll need to implement for a third and fourth job, so I cannot keep using the even/odd check. Here's my code for reference: (Please note that I only include relevant code) GameModeState.cpp // If changeJob's parameter number is 1, it increments the job. If number is 2, it only returns the current job int GameModeState::changeJob(int number) { // Default job is even (landman) static int job = 1; if (number == 1) { job = (job+1); return job; } else { return job; } } int GameModeState::getJob() { int currentJob = (changeJob(2)); return currentJob; } // If the player opens the "stat sheet", it changes their job void GameModeState::_statSheet(const String& message, const Awesomium::JSValue& input, Awesomium::JSValue& output) { changeJob(1); } GameModeState.h class GameModeState : public GameState::State { public: /// Changes the player's job if number is 1, or returns current job if number is 2 static int changeJob(int number); /// Returns the current job number by calling changeJob appropriately static int getJob(); private: // Opening the player sheet will change the player's job void _statSheet(const String& message, const Awesomium::JSValue& input, Awesomium::JSValue& output); }; ZoneMovementState.cpp (This is where I check for current job) #include "GameModeState.h" #include <EnergyGraphics/ZoneParser.h> void ZoneMovementState::_changeZone(const String& message, const Awesomium::JSValue& input, Awesomium::JSValue& output) { // If the number from getJob is even, the player is currently a geologist if (GameModeState::getJob()%2 == 0) { ZoneParser::getSingleton().load("../media/zones/geology_zone.xml", false); } else //otherwise they are a landman { ZoneParser::getSingleton().load("../media/zones/landman_zone.xml", false); } transitionHandler->go(); } I'm thinking either arrays or enums of the jobs will be the better way to deal with this, but I'm not sure how to implement this into my code. If you know a better way, please include examples or at least a point in the right direction. I will greatly appreciate it!
Don't use static variables to save anything like that inside a class. Use a member variable instead. IMO the easiest way to do something like that and make it extensible is using a enum: enum PlayerJob JOB_NONE = 0, JOB_GEOLOGIST, JOB_LANDMAN, ... NUM_JOBS // this element is optional but can be useful for range checking. }; ... PlayerJob job = JOB_NONE; ... switch(job) { case JOB_NONE: break; case JOB_GEOLOGIST: ... break; ... default: error("Unhandled palyer job: %d", job); break; } Also I'd think about somehow organizing such "job relevant" stuff into some kind of array or list or whatever to make it easier to call "job specific" things: std::map<PlayerJob,std::string> jobzones; jobzones.push_back(JOB_GEOLOGIST, "geozone.xml"); ... transitToZone(jobzones[job]);
Enums are nice, you may also think about using a std::stack or something similar for the GameState, so that you can push/pop etc.
You may want to look at the State pattern.