I hope someone can help me. In an effort to be more specific about what I really need, and trim down my code, I have changed from having a vector purely of my Class, to having a vector of objects of a new class, of which my original class is a type within.
I hope I have explained myself clearly up until this point. I will show the relevant classes:
class screen_area
{
private:
int my_id, my_x, my_y, my_width, my_height;
bool active=true;
public:
screen_area (int button_id=0, int x=0, int y=0, int width=0, int height=0, bool isactive=true)
{
my_id = button_id;
my_x = x;
my_y = y;
my_width = width;
my_height = height;
active = isactive;
}
~screen_area()
{}
class bet
{
private:
int wager = 0;
int multiplier = 0;
public:
screen_area area;
bet(int wager, int multiplier, screen_area area)
{};
~bet()
{};
There is a little more to them, but this is the bread and butter. Now previously I had used a member function within "screenarea", to return any value I had wanted from a specific object:
int getvalue(int value)
{
switch(value)
{
case 1 :
return my_id;
case 2 :
return my_x;
case 3 :
return my_y;
case 4 :
return my_width;
case 5 :
return my_height;
case 6 :
return active;
}
}
And I have modified a lookup function to use this member function on the screenarea that is a type contained within "bet".
int returnbuttonid(int mousex, int mousey, std::vector<bet> *buttons)
{
for (auto ep : *buttons )
{
if ((ep.area.getvalue(2) > mousex) && (ep.area.getvalue(3) > mousey))
{int id_value = ep.area.getvalue(1);
return id_value;
}
}
}
However... it returns garbage. I'm clearly missing something, but I am going through it logically and it all seems to make sense.
Sorry in advance if it is something simple! And I appreciate that this may seem long winded but I would really appreciate some help!
And just to be super clear... this is how I am calling it:
vector<bet> localbuttons; //Declaration of Vector
load_map("data.dat", &localbuttons); //load buttonmap using function
int buttonpressed = returnbuttonid(100,300, &localbuttons);
In response to a very speedy comment. It's clear that the problem at least starts with an unpublished piece of code. My vector of "bet" is not being filled with the arguments I am passing to it when I try to overload the constructor. I presumed I had corrected the syntax correctly when I created the new class "bet", but after probing the vector it is not showing any data.
In my function load_map:
bool load_map(std::string path, std::vector<bet> *buttons)
{
//setup file
ifstream inputFile( path.c_str() );
//
//The stuff in the middle here is irrelevant
//and I've take it out to make this tidier
buttons->push_back(bet(0,0, screen_area(id,x,y,width,height, true)));
}
return 0;
}
Now the only part of this that has changed since I had this function was working is:
buttons->push_back(bet(0,0, screen_area(id,x,y,width,height, true)));
So I am guessing this is where the problem originates. The variables are not overloading the default screen_area constructor. So when I:
cout << localbuttons[1].area.my_id << endl;
I always see whatever value I place in the default constructor. It is "0" in the constructor I have posted here, but if I change it, it changes correspondingly.
And I shouldn't have said garbage, I was at fault for thinking I had correctly identified the area of the problem, and trying to be concise. So I guess I should be asking first... How can I correctly overload this "screenarea" constructor?
The problem here was in the Constructor of the Bet class.
After having a look here:
http://www.cplusplus.com/doc/tutorial/classes/
I rewrote the constructor in the Bet class:
bet(int w, int m, int button_id=0, int x=0, int y=0,
int width=0, int height=0, bool isactive=true)
: area(button_id, x, y, width, height, isactive),
wager(w), multiplier(m)
{};
My apologies if I wasted anyone time with misdirection, and thanks for the sensible advice from Jonathon Potter.
I'm not sure why I thought you could call constructors within parentheses. My compiler didn't seem to complain about it, but from what I can gather - I was just creating a temporary object.
Related
I am pretty much new to OOP and C++ but have a project of "graph traversing" (sorry if there's a more formal term).
I am at the very beginning of the project where I have to initialize an 2D grid composed of cases.
I first thought of creating a class Case with 2D-position and a boolean state (occupied of free) as attributes, and a Grid class with a vector of vector of Cases representing the grid.
First I wondered if I'm going in the right direction on terms of Object-oriented programming, and if so I wondered how to initialize the grid in the constructor.
So far I have this for the Case class header :
class case_tab{
int x,y;
bool state;
public:
case_tab(int x_param, int y_param, bool state_param);
};
And the constructor :
case_tab::case_tab(int x_param, int y_param, bool state_param)
:x(x_param),y(y_param),state(state_param)
{}
But the problem comes for the grid constructor (named tableau, here you can see the header):
class tableau
{
int X, Y;
public:
std::vector<std::vector<case_tab>> tab;
tableau(int X_param, int Y_param);
};
Where I don't know how to initialize the grid (tableau) as a grid of free Cases disposed correctly.
I'm pretty sure this is of very basic difficulty but I can't find how to do so, and wonder if it doesn't come from my structure choice in the first place.
Hope someone can help me.
As you declared the attribute tab, it will be initialized by default. So you just have to do two loops so as to fill it. Here is a proposal:
tableau::tableau(int X_param, int Y_param)
: X(X_param), Y(Y_param) {
for(int i = 0; i < X; i++) {
std::vector<case_tab> row;
row.reserve(Y);
for(int j = 0; j < Y; j++) {
row.emplace_back(i, j, false);
}
tab.push_back(row);
}
}
emplace_back generates and adds case_tab objects by calling the constructor that you defined, and reserve allocates memory for the initialized objects.
You should also change tab visibility to private, so as to prevent adding unexpected items to it.
Trying to compile my code in Xcode, but I am obviously running into some problems as I get the error in the title. Here is the code for my header file called "myClasses.h":
#ifndef myClasses_h
#define myClasses_h
class Star
{
public:
Star(int x,int y)
{
int xPos = x;
int yPos = y;
}
};
#endif
So I obviously want a constructor for Star so I can declare a Star object like this:
Star sol(10,30);
Then the code in my "main.cpp":
#include <iostream>
#include <math.h>
#include <stdlib.h>
#include <vector>
#include "myClasses.h" //includes the Star class
bool checkOverlap(Star check, int a, int b)
{
double diffX = a - check.xPos;
double diffY = b - check.yPos;
double checkDist = sqrt( pow( diffX,2.0 ) + pow( diffY,2.0) );
if( checkDist > 20 )
return true;
else
return false;
};
int main()
{
//some other code here with no errors
};
Here in the main file I get the error, so I am lost as to what is going wrong? Am I using incorrect syntax to access the object's member variables? Shouldn't the code below print 10:
Star sol(10,30);
cout << sol.xPos
If not, how do I rewrite my class so it behaves like that or how do I properly access the member variables in the constructor?
You need to declare the variables in your class, you can't do that in the body of the constructor as those will be temporary variables not associated with the class instance. This will leave the xPos and yPos as their default values (which is 0) which is probably not what you want. Try something like this instead:
class Star
{
public:
int xPos;
int yPos;
Star(int x,int y):
xPos(x), yPos(y) //initializing the variables here
{
}
};
I've used a member initializer list here to initialize the members.
It's worth noting that this is likely not the best design for a class, you probably want to make xPos and yPos private along with some functions to change those values. You probably want to read up about encapsulation. Essentially you want to hide away information so that people don't need to know the internals of how your classes work in order to use them. This big benefit is that this lets people use your code without needing to worry about the internals of how your code works and lets them keep using your code without having to change their code even if some of those internal details happen to change over time. Imagine the hassle if you had to know exactly how your network card driver was programmed in order to write an application that used the network. It would be a big pain, you might have to change your code whenever you updated the other code, however because this driver code has (hopefully) been encapsulated you don't need to worry about these details in order to use that code. The code and classes you write are no different, think about the people who will use them, try to make it easy for them to use your code.
A possibly better design would be to do something like this:
class Star
{
private:
int xPos;
int yPos;
public:
Star(int x,int y):
xPos(x), yPos(y) //initializing the variables here
{
}
int get_xPos(){
return xPos;
}
int get_yPos(){
return yPos;
}
};
Now in your main code you change:
Star sol(10,30);
cout << sol.xPos;
To:
Star sol(10,30);
cout << sol.get_xPos();
The benefits of doing it this way really start to become more obvious when you get larger software or you have to deal with changes. For example later on the code changes and we decide to store the coordinates in a coordinates struct:
struct coords{
int xPos;
int yPos;
}
class Star
{
private:
coords Pos;
public:
Star(int x,int y):
Pos{x,y} //initializing the variables here
{
}
int get_xPos(){
return Pos.xPos;
}
int get_yPos(){
return Pos.yPos;
}
};
The original code would break:
Star sol(10,30);
cout << sol.xPos; //There's no xPos anymore
but with our new design this:
Star sol(10,30);
cout << sol.get_xPos();
Works just like before! We only needed to change the code in one place in the getter function get_xPos() and everthing will keep working just like it did before we made the changes.
Declare member variables:
class Star
{
public:
int xPos;
int yPos;
Star(int x,int y)
{
xPos = x;
yPos = y;
}
};
so curiosity got me looking for an alternative method of returning specific data or part of a structure. I currently have a structure and class similar, if not exact to this:
struck Pos {
Int x_{0},
y_{0},
z_{0};
};
class Object {
private:
Pos xyz_{ 0, 0, 0 };
public:
const Pos getPos() { return xyz_; }
};
Now this is without constructors and stuff. Anyway the I'm trying/wanting to return the x_ of xyz_ now I could just do:
const int getPosX() { return xyz_.x_; }
but that seems impractical as I'd have to do that 3 times as well as modify my main code to compensate for the changes. So wondered if there's an easier or better method for doing something like:
Object ob; // Empty I know but you get the idea?
int xValue = ob.getPos.x_;
Any help is deeply appreciated.
ob.getPos().x_;
Worked, simply overlooked the ().
I have a relatively simple question but I cant seem to find an answer specific for my case and I just may not be approaching this problem the right way. I have a class that looks like this:
struct tileProperties
{
int x;
int y;
};
class LoadMap
{
private:
ALLEGRO_BITMAP *mapToLoad[10][10];
tileProperties *individualMapTile[100];
public:
//Get the struct of tile properties
tileProperties *getMapTiles();
};
I have an implementation that looks like this for the getter function:
tileProperties *LoadMap::getMapTiles()
{
return individualMapTile[0];
}
I have code in the LoadMap class that will assign 100 tile properties for each struct in the array. I want to be able to access this array of structs in my main.cpp file but I just cant seem to find the right syntax or approach. My main.cpp looks like this.
struct TestStruct
{
int x;
int y;
};
int main()
{
LoadMap _loadMap;
TestStruct *_testStruct[100];
//This assignment will not work, is there
//a better way?
_testStruct = _loadMap.getMapTiles();
return 0;
}
I realize that there are many approaches to this, but I'm trying to keep this implementation as private as possible. If someone could please point me in the right direction I would greatly appreciate it. Thank you!
TestStruct *_testStruct;
_testStruct = _loadMap.getMapTiles();
This will get you a pointer to the first element in the array returned. You can then iterate through the other 99.
I would highly recommend using vectors, or another container, and writing getters that don't return pointers to bare arrays like that.
First of all, here, why do we need TestStruct, you can use "tileProperties" structure itself...
And imp thing,
tileProperties *individualMapTile[100]; is array of pointers to the structure.
Hence, individualMapTile will have pointers in it.
You have returned the first pointer, hence you can access the first structure only. What about the others????
tileProperties** LoadMap::getMapTiles()
{
return individualMapTile;
}
int main()
{
LoadMap _loadMap;
tileProperties **_tileProperties;
_tileProperties = _loadMap.getMapTiles();
for (int i=0; i<100;i++)
{
printf("\n%d", (**_tileProperties).x);
_tileProperties;
}
return 0;
}
Use vectors instead of arrays where possible. Also consider an array/vector of TestStruct directly rather than pointers to them. I can't tell if that would be appropriate for you from your code sample.
class LoadMap
{
public:
typedef vector<tileProperties *> MapTileContainer;
LoadMap()
: individualMapTile(100) // size 100
{
// populate vector..
}
//Get the struct of tile properties
const MapTileContainer& getMapTiles() const
{
return individualMapTile;
}
MapTileContainer& getMapTiles()
{
return individualMapTile;
}
private:
MapTileContainer individualMapTile;
};
int main()
{
LoadMap _loadMap;
LoadMap::MapTileContainer& _testStruct = _loadMap.getMapTiles();
}
I've tried to SSCE my problem as best possible, but it involves mulitple objects defined in C++. They are simple, though - I think its best if I share my code before explaining further:
#include <iostream>
#include <vector>
struct Cell {
bool visited;
Cell():visited(false) {}
void setVisited(bool val) {visited = val;}
bool beenVisited() {return visited;}
};
struct Vector2D
{
int size;
std::vector<Cell> myVector;
Vector2D(int n): size(n), myVector(n*n) {}
Cell& getAt(int x, int y) {return myVector[((x * size) +y)];}
};
int main()
{
Vector2D vec = Vector2D(1);
Cell cell= vec.getAt(0,0);
cell.setVisited(true);
cell = vec.getAt(0,0);
if (cell.beenVisited() == false)
std::cout << "Why is this not true like I set it a moment ago?\n";
}
I apologize sincerely for all of this, but it is needed to make the point. As you can see, I getAt() what I think to be Cell object, set its visited instance data to true, and then switch off to another cell. Why, then, when i come back to that same cell, find that the visited value is false instead of true?! It's like it isn't registering my private data change!
What is the best way to do this?
Thanks
Cell cell= vec.getAt(0,1);
copy of object.
Use
Cell& cell = vec.getAt(0, 1);
or simply
vec.getAt(0, 1).setVisited(true);
EDIT.
This code should works.
using namespace bob;
Vector2D vec = Vector2D(5);
vec.setAt(0,0, Cell(0,0));
vec.setAt(0,1, Cell(0,1));
vec.setAt(0,2, Cell(0,2));
Cell& cell= vec.getAt(0,1);
cell.setVisited(true);
Cell cell1 = vec.getAt(0,2);
cell1 = vec.getAt(0,1);
if (cell1.beenVisited() == false)
{
std::cout << "Why is this not true like I set it a moment ago?" << std::endl;
}
http://liveworkspace.org/code/53634eda052a07885d4e6c062a0fd302
ForEveR's answer is correct -- you need to store the value returned by getAt() in a reference variable, rather than copying it into a value variable.
You might consider explicitly declaring that the "Cell" class should never be copied, which will help you catch this type of error sooner. This can be done by declaring a private copy constructor (with no body); or if you're using boost, then it can be done by inheriting from the base class "boost::noncopyable" (docs for noncopyable).