Evaluating the constructor equivalent of a variable - c++

I have the constructor
class MyFrame : public wxFrame { // defines the options on the top bar of the screen here we have:
public:
MyFrame();
private:
void OnHello(wxCommandEvent& event); // hello option
void OnExit(wxCommandEvent& event); // exit option
void OnAbout(wxCommandEvent& event); // about option
void OnHelp(wxCommandEvent& event); // event option
// void OnCourseTextBoxClicked(wxCommandEvent &event);
void OnOneHundredLevelDisplayGpButtonClicked(wxCommandEvent &event);
void OnTwoHundredLevelDisplayGpButtonClicked(wxCommandEvent &event);
void OnThreeHundredLevelDisplayGpButtonClicked(wxCommandEvent &event);
void OnFourHundredLevelDisplayGpButtonClicked(wxCommandEvent &event);
void OnFiveHundredLevelDisplayGpButtonClicked(wxCommandEvent &event);
void OnDisplayCgpaButtonClicked(wxCommandEvent &event);
// Common Courses equating their credit load
/* 100 LEVEL FIRST SEMESTER */
int CHM111 = 3;
int CHM113 = 3;
int MTH111 = 3;
int MTH112 = 3;
int PHY111 = 3;
int PHY113 = 3;
int GST111 = 2;
int GST112 = 2;
/* 100 LEVEL SECOND SEMESTER */
int CHM122 = 3;
int CHM124 = 3;
int MTH123 = 3;
int MTH125 = 3;
int PHY109 = 2;
int PHY124 = 4;
int GST121 = 2;
int GST122 = 2;
int GST123 = 2;
int LEVEL_TOTAL_100 = 47;
}
And somewhere else in the code base, some text is entered into a text box. The text box is supposed to contain one of the variables defined in the constructor which evaluate to their respective integers.
When the text box's content is evaluated e.g.:
course_one_text_box->GetValue();
evaluates
CHM111
I want to grab the constructor integer value for the CHM111 which is 3. I want to employ this value in a mathematical formula.
How do I do this?
Is there a particular syntax that grabs the constructor recorded version of the variable instead?
Thanks.

wxTextCtrl works with wxString, not with numbers.
But it's really easy to get a number from a wxString: Use wxString::ToCLong. For example:
long value;
mystring = mytextctrl->GetValue();
if ( ! mystring.ToCLong(&value) )
some message here, conversion failed (not a number)
//Your comparisons:
if ( value == (long)CHM111 )
....
So, if the user enters 3 the 'if' is true because CMH111 is initialized as 3
Notice the (long) cast from an int to avoid compiler warning. Why not use long instead of int for the type of CHMxxx?
What is not possible in C++ is to compare against the name of a variable.

#Alvindera97,
Is your program should restrict the user to enter only those constants? Then you have a wrong tool for the job!
Look at the wxComboBox/wxChoice. This way the user will have the only choice to select from the list and you won't need to keep those constants definitions in the class.
Hope this helps!

Related

How to Choose Function Based on Loop Iterator

Part of my problem in finding a solution here is likely that I don't know the correct terms for what it is I am asking. For that, I beg forgiveness in advance.
For a microcontroller, I have a list of pins I wish to initiate at the same time. Each has it's own ISR, and calls the same member of a class for each instance but with a pin number as an argument.
I am trying to attach each pin in the array to its corresponding ISR but I would like to choose which ISR by the pin's index. This is Mailer Codeā„¢ and likely does not compile but I believe it's enough to get the idea:
#define PIN1 4
#define PIN2 9
#define PIN3 10
#define PIN4 8
#define PIN5 12
PinAct *pPinact; // Pointer to Counter class
static ICACHE_RAM_ATTR void HandleInterruptsStatic1(void) {
pPinact->handleInterrupts(1);
}
static ICACHE_RAM_ATTR void HandleInterruptsStatic2(void) {
pPinact->handleInterrupts(2);
}
static ICACHE_RAM_ATTR void HandleInterruptsStatic3(void) {
pPinact->handleInterrupts(3);
}
static ICACHE_RAM_ATTR void HandleInterruptsStatic4(void) {
pPinact->handleInterrupts(4);
}
static ICACHE_RAM_ATTR void HandleInterruptsStatic5(void) {
pPinact->handleInterrupts(5);
}
class PinAct {
public:
PinAct() {};
void handleInterrupts(int);
}
void PinAct::PinAct() {
int actPins[] = {PIN1, PIN2, PIN3, PIN4, PIN5};
for (int i = 0; i <= sizeof(actPins); i++) {
pinMode(actPin[i], INPUT)
attachInterrupt(digitalPinToInterrupt(KEG1), HandleInterruptsStatic + i, FALLING);
}
}
void PinAct::handleInterrupts(int pin) { // Bubble Interrupt handler
// Do something with pin
}
The goal is to actually make the attachInterrupt(digitalPinToInterrupt(KEG1), HandleInterruptsStatic + i, FALLING); work, choosing which ISR by virtue of the index i.
I need to make other decisions about whether or not to assign the ISR, so concatenating the ISR name to be assigned is desirable.
attachInterrupt(/* ... */, HandleInterruptsStatic + i, /* ... */);
// ^^^^^
In order to select the function you want to call at runtime depending on some integer index i you can use an array of function pointers:
typedef void (*FunctionPointer_t)(void);
FunctionPointer_t functions[] = {
HandleInterruptsStatic1,
HandleInterruptsStatic2,
// ...
};
// to use:
functions[i]();

How can I distinguish my characters in a vector? SFML 2.4.1

I am using push_back to add identical characters and for some reason these characters all have the same stats all the time.
Battle.cpp:
void Battle::InitalizeUser()
{
user.t_Pokemon.clear();
user.t_Item.clear();
user.currentPokemon_U = 0;
user.t_Pokemon.push_back(&uF1);
user.t_Pokemon.push_back(&uF1);
user.t_Pokemon.push_back(&uW3);
user.t_Pokemon.push_back(&uW3);
user.t_Pokemon.push_back(&uG5);
user.t_Pokemon.push_back(&uG5);
user.t_Item.push_back(&uI1);
user.t_Item.push_back(&uI2);
for (unsigned int i = 0; i < user.t_Pokemon.size(); i++)
{
user.t_Pokemon.at(i)->poke_health = 100;
user.t_Pokemon.at(i)->poke_isFainted = false;
}
assert(user.t_Pokemon.size() == 6);
assert(user.t_Item.size() == 2);
}
So if uF1 health is reduced all uF1 characters will suffer the same reduction, but I don't want all the others uF1 to suffer the reduction, I want to be able to distinguish them and have only one specific character affected.
How can I do that?
Pokemon.cpp:
void Pokemon::attackNormal(Pokemon * opponentPokemon)
{
opponentPokemon->poke_health = opponentPokemon->poke_health - 20;
opponentPokemon->changeIfFainted();
assert(opponentPokemon->poke_health <= 100 && opponentPokemon->poke_health >= 0);
}
Battle.h:
class Battle
{
private:
static Trainer user;
static Trainer ash;
static IntRect user_Rect;
static IntRect ash_Rect;
// User's pokemon
static Fire uF1;
static Water uW3;
static Grass uG5;
static Item uI1;
static Item uI2;
}
uF1 : Pokemon.h
class Fire : public Pokemon
{
public:
Fire();
Fire(string name);
virtual ~Fire();
void specialAttack(Pokemon * opponentPokemon);
void changeWeather();
void Draw(RenderWindow &window);
};
The problem is that your vector contains copies of a pointer what is not equivalent to having different copies of an actual object.
It seems that you are passing same pointers several times in order to achieve object copy which is not a case.
You should first declare all your objects and then add their addresses to the vector.
Additional note: you don't have to create a variable for every object you use. You could also create an array of objects.

What to use for initial values? Struct, enum or class, #defines c++

It's kind of a shame to ask this question and probably will fit better in the Code Review site, so sorry in advance.
My question is the following (can be extensible for other languages since is more OOP):
I have a class:
class Unit
{
public:
Unit(Type);
Type type;
private:
int weaponry;
int shielding;
int hull;
int rapid_fire;
}
with an enum to differenciate between different types of units.
enum Type{
Cruiser,
Missile
};
All the units will be initialize with a default value (plus a factor, depending in external variable).
Unit::Unit(Type type)
{
this->type = type;
int weaponry, shielding, hull,rapid_fire;
switch(type){
case Cruiser:
weaponry = 2700;
shielding = 50;
hull = 400;
rapid_fire = 5;
break;
case Missile:
weaponry = 200;
shielding = 20;
hull = 80;
rapid_fire = 0;
break;
}
this->weaponry = weaponry ; //+ whatever
this->shielding = shielding; //+ whatever
this->hull = hull; //+ whatever
this->rapid_fire = rapid_fire;
}
I will also have a method that will change the values of the object, such as the typical
setHull(int newHull){this->hull = newHull}
In one of these methods, i want to revert one of the private variables to its default value, in the example case, if is Cruiser this->shielding = 50, if its a missile = 20.
My questions are the following.
Am i doing something wrong?
I have several options to keep the defaults values, either with (the one I would "noobly" will choose)
#define initial_cruiser_shielding 50
either with enum:
enum shielding_init{
cruiser_i = 50,
missile_i = 20
};
to have default instances of the basic objects, and then just copy them and create as many new objects I need.
Thanks in advance!
My recommendation will be to create private static member functions that can return default values.
class Unit
{
public:
Unit(Type);
Type type;
int set_default_weaponry()
{
weaponry = get_default_weaponry();
}
int set_default_shielding()
{
shielding = get_default_shielding();
}
int set_default_hull()
{
hull = get_default_hull();
}
int set_default_rapid_fire()
{
rapid_fire = get_default_rapid_fire();
}
private:
int weaponry;
int shielding;
int hull;
int rapid_fire;
static int get_default_weaponry();
static int get_default_shielding();
static int get_default_hull();
static int get_default_rapid_fire();
}

How to write function for multiple analog pins? (arduino)

So I'm writing this little function for some pot pins. The pot sends a value only when its being turned, at rest, it sends nothing. Which is how I want it to function.
It works fine with one pin.
I've gotten it to a point where it half works with multiple pins. So if I call it twice in the loop with two pins, I get back the right values on both those pins. But I loose the functionality of the if statement. Basically I can't figure out the last half of this. Arrays have been suggested I'm just unsure of how to proceed.
Suggestions? Thank you.
byte pots[2] = {A0, A2};
int lastPotVal = 0;
void setup(){
Serial.begin(9600);
}
void loop(){
// get the pin out of the array
rePot(pots[0]);
rePot(pots[1]);
delay(10);
}
void rePot(const int potPin){
// there is probably an issue around here somewhere...
int potThresh = 2;
int potFinal = 0;
int potVal = 0;
// set and map potVal
potVal = (analogRead(potPin));
potVal = map(potVal, 0, 664, 0, 200);
if(abs(potVal - lastPotVal) >= potThresh){
potFinal = (potVal/2);
Serial.println(potFinal);
lastPotVal = potVal;
} // end of if statement
} // end of rePot
This uses a struct to mange a pot and the data associated with it (the pin it's on, the last reading, threshold, etc). Then, the rePot() function is changed to take one of those structs as input, instead of just the pin number.
struct Pot {
byte pin;
int threshold;
int lastReading;
int currentReading;
};
// defining an array of 2 Pots, one with pin A0 and threshold 2, the
// other with pin A2 and threshold 3. Everything else is automatically
// initialized to 0 (i.e. lastReading, currentReading). The order that
// the fields are entered determines which variable they initialize, so
// {A1, 4, 5} would be pin = A1, threshold = 4 and lastReading = 5
struct Pot pots[] = { {A0, 2}, {A2, 3} };
void rePot(struct Pot * pot) {
int reading = map(analogRead(pot->pin), 0, 664, 0, 200);
if(abs(reading - pot->lastReading) >= pot->threshold) {
pot->currentReading = (reading/2);
Serial.println(pot->currentReading);
pot->lastReading = reading;
}
}
void setup(){
Serial.begin(9600);
}
void loop() {
rePot(&pots[0]);
rePot(&pots[1]);
delay(10);
}
A slightly different take on this is to change rePot() into a function that takes the whole array as input, and then just updates the whole thing. Like this:
void readAllThePots(struct Pot * pot, int potCount) {
for(int i = 0; i < potCount; i++) {
int reading = map(analogRead(pot[i].pin), 0, 664, 0, 200);
if(abs(reading - pot[i].lastReading) >= pot[i].threshold) {
pot[i].currentReading = (reading/2);
Serial.println(pot[i].currentReading);
pot[i].lastReading = reading;
}
}
}
void loop() {
readAllThePots(pots, 2);
delay(10);
}

Inherited variables are not reading correctly when using bitwise comparisons

I have a few classes set up for a game, with XMapObject as the base, and XEntity, XEnviron, and XItem inheriting it.
MapObjects have a number of flags, one of them being MAPOBJECT_SOLID. My problem is that XEntity is the only class that correctly detects MAPOBJECT_SOLID. Both Items are Environs are always considered solid by the game, regardless of the flag's state. What is important is that Environs and Item should almost never be solid.
Each class has a very basic preliminary constructor, just initializing all varibles to zero or NULL. During the CreateX() phase, Objects are linked into the map, set into a linked linked list.
Both XItem and XEnviron are a tad sloppy. They are both new, and in the middle or my debugging attempts.
Here are the relevent code samples:
XMapObject:
#define MAPOBJECT_ACTIVE 1
#define MAPOBJECT_RENDER 2
#define MAPOBJECT_SOLID 4
class XMapObject : public XObject
{
public:
Uint8 MapObjectType,Location[2],MapObjectFlags;
XMapObject *NextMapObject,*PrevMapObject;
XMapObject();
void CreateMapObject(Uint8 MapObjectType);
void SpawnMapObject(Uint8 MapObjectLocation[2]);
void RemoveMapObject();
void DeleteMapObject();
void MapObjectSetLocation(Uint8 Y,Uint8 X);
void MapObjectMapLink();
void MapObjectMapUnlink();
};
XMapObject::XMapObject()
{
MapObjectType = 0;
Location[0] = 0;
Location[1] = 1;
NextMapObject = NULL;
PrevMapObject = NULL;
}
void XMapObject::CreateMapObject(Uint8 Type)
{
MapObjectType = Type;
}
void XMapObject::SpawnMapObject(Uint8 MapObjectLocation[2])
{
if(!(MapObjectFlags & MAPOBJECT_ACTIVE)) { MapObjectFlags += MAPOBJECT_ACTIVE; }
Location[0] = MapObjectLocation[0];
Location[1] = MapObjectLocation[1];
MapObjectMapLink();
}
XEntity:
XEntity *StartEntity = NULL,*EndEntity = NULL;
class XEntity : public XMapObject
{
public:
Uint8 Health,EntityFlags;
float Speed,Time;
XEntity *NextEntity,*PrevEntity;
XItem *IventoryList;
XEntity();
void CreateEntity(Uint8 EntityType,Uint8 EntityLocation[2]);
void DeleteEntity();
void EntityLink();
void EntityUnlink();
Uint8 MoveEntity(Uint8 YOffset,Uint8 XOffset);
};
XEntity::XEntity()
{
Health = 0;
Speed = 0;
Time = 1.0;
EntityFlags = 0;
NextEntity = NULL;
PrevEntity = NULL;
IventoryList = NULL;
}
void XEntity::CreateEntity(Uint8 EntityType,Uint8 EntityLocation[2])
{
CreateMapObject(EntityType);
SpawnMapObject(EntityLocation);
if(!(MapObjectFlags & MAPOBJECT_SOLID) { MapObjectFlags += MAPOBJECT_SOLID; }
EntityFlags = ENTITY_CLIPPING;
Time = 1.0;
Speed = 1.0;
EntityLink();
}
void XEntity::EntityLink()
{
if(StartEntity == NULL)
{
StartEntity = this;
PrevEntity = NULL;
NextEntity = NULL;
}
else
{
EndEntity->NextEntity = this;
}
EndEntity = this;
}
XEnviron:
class XEnviron : public XMapObject
{
public:
Uint8 Effect,TimeOut;
void CreateEnviron(Uint8 Type,Uint8 Y,Uint8 X,Uint8 TimeOut);
};
void XEnviron::CreateEnviron(Uint8 EnvironType,Uint8 Y,Uint8 X,Uint8 TimeOut)
{
CreateMapObject(EnvironType);
Location[0] = Y;
Location[1] = X;
SpawnMapObject(Location);
XTile *Tile = GetTile(Y,X);
Tile->Environ = this;
MapObjectFlags = MAPOBJECT_ACTIVE + MAPOBJECT_SOLID;
printf("%i\n",MapObjectFlags);
}
XItem:
class XItem : public XMapObject
{
public:
void CreateItem(Uint8 Type,Uint8 Y,Uint8 X);
};
void XItem::CreateItem(Uint8 Type,Uint8 Y,Uint8 X)
{
CreateMapObject(Type);
Location[0] = Y;
Location[1] = X;
SpawnMapObject(Location);
}
And lastly, the entity move code. Only entities are capable of moving themselves.
Uint8 XEntity::MoveEntity(Uint8 YOffset,Uint8 XOffset)
{
Uint8
NewY = Location[0] + YOffset,
NewX = Location[1] + XOffset;
if((NewY >= 0 && NewY < MAPY) && (NewX >= 0 && NewX < MAPX))
{
XTile *Tile = GetTile(NewY,NewX);
if(Tile->MapList != NULL)
{
XMapObject *MapObject = Tile->MapList;
while(MapObject != NULL)
{
if(MapObject->MapObjectFlags & MAPOBJECT_SOLID)
{
printf("solid\n");
return 0;
}
MapObject = MapObject->NextMapObject;
}
}
if(Tile->Flags & TILE_SOLID && EntityFlags & ENTITY_CLIPPING)
{
return 0;
}
this->MapObjectSetLocation(NewY,NewX);
return 1;
}
return 0;
}
What is wierd, is that the bitwise operator always returns true when the MapObject is an Environ or an Item, but it works correctly for Entities. For debug I am using the printf "Solid", and also a printf containing the value of the flag for both Environs and Items.
Any help is greatly appreciated, as this is a major bug for the small game I am working on. I am also very new at Object Oriented programming, anything tips, suggestions and/or criticism are also welcome.
Your problem appears to be that you never initialize MapObjectFlags in any classes other than XEnviron so, as a basic type, it will have an unspecified value in XItem, XEntity and other XMapObject derived objects. I suggest that, as a member of XMapObject you explicitly initialize it to a known value.
As a rule, it is generally a good idea to ensure that all members of basic type are explicitly initialized in the initializer list of every constructor that you define.
e.g.
XMapObject()
: MapObjectFlags(0)
, // ... other initializers
{
// Other initializations
}
You can't (legally) be calling XEntity::MoveEntity on a MapObject or Environ because they don't have such a method. If you're using static_cast to change your object pointer into an XEntity so you can call MoveEntity on it, then you really have no guarantees about how the bit operation will work. In some implementations, things may appear to work in MoveEntity, but what's actually happening is it's interpreting the other object's memory as an XEntity. When it tries to access the offset where it believes MapObjectFlags exists, it's not actually there and always has that bit set to 1.
I figured out the problem earlier today - It didn't have any relation to OO programming, inheritance, or bitwise; it was a simple scope error.
The problem was in the fact that during my quick test to get an Environ in game, I declared the new variable inside of the control switch sequence, so the next time any control was used, the Environ would act in unpredictable ways.
switch(Event.key.keysym.sym)
{
...
case SDLK_c: { XEnviron Environ; Environ.InitEnviron(...); }
...
}