Store cursor position in class object (ncurses c++) - c++

I am using QTCreator to compile my c++ code and the <curses.h> library.
Let us say we have the following class definition (.h):
struct coordinateYX
{
int y;
int x;
coordinateYX(long int yPos, long int xPos);
coordinateYX() {}
}
class Rogue
{
private:
long int health;
coordinateYX heroPosition;
public:
long int getHealth();
void setHealth(long int initHealth);
void healthChange(long int vDelta);
coordinateYX getHeroPosition();
void setHeroPosition(coordinateYX hPos);
};
and (.cpp):
coordinateYX::coordinateYX(long int yPos, long int xPos) : y{yPos}, x{xPos} {}
long int Rogue::getHealth() {return health;}
void Rogue::setHealth(long int initHealth) {health = initHealth;}
void Rogue::healthChange(long int vDelta) {health += vDelta;}
coordinateYX Rogue::getHeroPosition() {return heroPosition;}
void Rogue::setHeroPosition(coordinateYX hPos)
{
heroPosition.y = hPos.y;
heroPosition.x = hPos.x;
}
In my main.cpp, I am trying to store the current cursor position into an instantiation of Rogue:
Rogue Hero;
getyx(stdscr, Hero.getHeroPosition().y, Hero.getHeroPosition().x);
But I always get an error:
using temporary as lvalue [-fpermissive]
It also shows this below as part of the error which is in the <curses.h> file
#define getyx(w, y, x) (y = getcury(w), x = getcurx(w))
Although I can simply store these values in another struct initialized in main.cpp, how can I store the x and y positions directly in the class data members?
Thank you.

The quickest solution would be to change getHeroPosition to return a reference instead of value:
coordinateYX& Rogue::getHeroPosition() {return heroPosition;}
The problem is here you are trying to assign to the Rogue position:
getyx(stdscr, Hero.getHeroPosition().y, Hero.getHeroPosition().x);
This is equivalent to:
Hero.getHeroPosition().y = getcury(stdscr);
Hero.getHeroPosition().x = getcurx(stdscr);
But getHeroPosition returns the position by value (it returns a copy, an rvalue). If you assign a value to that temporary copy it will just be lost. The solution is to assign to a reference to the actual Rogue position (an lvalue).
Alternatively, you can use your existing setPosition function:
coordinateYX position;
getyx(stdscr, position.X, position.Y);
Hero.setPosition(position);

Related

C++ What is the point of using const in a class setter function?

I am going through a text book to freshen up my (fairly bad) C++ knowledge and I came across this code example (shortened):
class MyClass{
private:
int count;
double price;
string name;
public:
void setValues(const int&, const double&, const string&);
};
void MyClass::setValues(const int& c, const double& p, const string& n){
count = c;
price = p;
name= n;
}
int main(){
myClass pOne;
pOne.setValues(5, 0.75, "Kiwi");
return 0;
}
The Way I understand the const keyword and the way it was described in the book thus far is that I can use it to declare constants, which should not be subject to change. This is better for the compiler since it knows that the values won't change.
But here I use const every time I set values
void MyClass::setValues(const int& a, const double& p, const string& b)
once the values of pOne are set, I can change them over and over with the setValues function, so what is the point of making them const?
once the values of pOne are set, I can change them over and over with the setValues function, so what is the point of making them const?
This is flawed logic. Consider this small example:
const int x = 42;
int y = x;
The value of x is assigned to y. Just because x is constant does not imply that y is too. You can change the value of y afterwards.
In the function signature the const means the usual: You cannot modify the parameters. It would be odd if a setter would change them.
struct foo {
int value = 42;
void set(int& x) {
value = x;
x = 42; // what ?!?
}
};
int main() {
int a = 2;
foo f;
f.set(x);
std::cout << x; // prints 42.... what?!?
const int b = 3;
f.set(b); // error because b is const :(
}
The setter takes its parameters by constant references because it tries to avoid a copy (hence reference) and parameters are not modified by the call (hence const).
Passing int as const int& however, is not really recommended, because it isn't cheaper than passing the int by value.

Segmentation fault when using vectors in the class and constructor

I was doing a list of programming projects, and this project is to make a 15 puzzle (slide puzzle). I was working on the project when I hit a small roadblock.
My code compiles just fine, but when I run it, I get a segmentation fault at line 12: pos[0] = x;
#include <iostream>
#include <vector>
#include <stdlib.h>
#include <time.h>
using namespace std;
class Tile{
private:
vector<int> pos;
int value;
public:
Tile(int x, int y, int value_){
pos[0] = x;
pos[1] = y;
value = value_;
}
~Tile(){}
int getPos(int a){return pos[a];}
void setPos(int a, int b){pos[a] = b;}
};
int main(){
Tile tile1(1, 2, 10);
Tile* t1;
t1 = &tile1;
// returns position "x"
cout << t1->getPos(0);
return 0;
}
I mean, I could just do the whole project without having to use vectors/arrays to handle the position, but I do still want to know, for my own understanding in the future, why this doesn't work.
Based on the debug that I ran, the program is having trouble initializing the value of the pos[] vector.
Another issue: probably related, I tried setting the size of the vector when it was instantiated.
vector<int> pos(2);
But then I get the debug error:
error: expected identifier before numeric constant
Not sure whats going on here. I've tried a bunch of different things but I can't seem to figure out why my vectors don't work inside of classes.
I'm sure there are a hundred ways I could have done this little piece better, and I would love to know how you would have fixed it, but I also need to know what is wrong, specifically in the context of what I have written and tried.
Thanks.
I tried setting the size of the vector when it was instantiated.
vector<int> pos(2);
But then I get the debug error:
error: expected identifier before numeric constant
That's a compilation error, not a debug error.
You can't initialise members like that. However, you can (and should) initialise them using the parent constructor:
Tile(int x, int y, int value_)
: pos(2)
{
pos[0] = x;
pos[1] = y;
value = value_;
}
Currently you're just leaving your vector empty then accessing (and writing to!) elements that don't exist.
You really don't want a vector for this, anyway: that's a lot of dynamic allocation. How about a nice array? Or just two ints.
As mentioned in other answers, your vector is empty and your code is attempting to assign non-existent elements.
The solution is to always use initialisers instead of assignment. Rewrite your constructor as follows:
Tile(int x, int y, int value) :
pos{x, y},
value{value} {}
Note that the constructor body is now empty. All initialisation happens where it should — in the initialiser list.
Apart from that, your class does not need an explicitly defined destructor; the default destructor works just fine.
There are other issues with this class — for instance, what happens when the user does tile.setPos(3, 4)? A rule of thumb of good API design is to make it impossible to misuse the API.
Here’s how I would write your Tile class instead:
struct Tile {
int x;
int y;
int value;
Tile(int x, int y, int value) : x{x}, y{y}, value{value} {}
};
The getter and setter in your case wasn’t really doing any meaningful work. There’s an argument to be made to hide all data members behind accessors to future-proof access control. I’m no longer convinced this is actually useful but just in case, here’s a solution with that, too:
class Tile {
int x_;
int y_;
int value_;
public:
Tile(int x, int y, int value) : x_{x}, y_{y}, value_{value} {}
int x() const { return x; }
int& x() { return x; }
int y() const { return y; }
int& y() { return y; }
int value() const { return value; }
};
This makes x and y readable and writable (via assignment: t.x() = 42;), and value only readable. Other APIs are possible, with different sets of trade-offs. The important thing is to be consistent.
Your constructor doesn't set the size, so when you try to access/modify its contents, you are probably getting the exception.
Tile(int x, int y, int value_) : pos(2) {
pos[0] = x;
pos[1] = y;
value = value_;
}
You can use the initialization list of the constructor to call the vector's constructor, as in the code above.
There are couple of issue in the given code, which I have resolved and added comment in the code.
Issue in setPos and getPos might raise segmentation fault must be handle.
Added checks for the same.
#include <iostream>
#include <vector>
#include <stdlib.h>
#include <time.h>
using namespace std;
class Tile{
private:
vector<int> pos;
int value;
public:
Tile(int x, int y, int value_){
pos.push_back(x); // this is equivalent to pos[0] = x, in this case
pos.push_back(y); // this is equivalent to pos[0] = y, in this case
value = value_;
}
~Tile(){}
int getPos(int a){
if(a >= pos.size()){
return -1; // if a is greater than size then pos[a] will raise the segmentation fault
}
return pos[a];
}
void setPos(int a, int b){
if(a >= pos.size()){
pos.resize(a+1); // to avoid segmentation fault, we are increasing the size if the given index is higher
// resize initialise the value with 0 as default value.
}
pos[a] = b;
}
};
int main(){
Tile tile1(1, 2, 10);
Tile* t1;
t1 = &tile1;
// returns position "x"
cout << t1->getPos(0);
return 0;
}

Pointer arguments in void function returning inconsistent values

This might be a stupid simple thing I'm overlooking, but I am setting values in the Data::Data(char *DataType...) function as they are being passed in, and as I hover over them, they are setting fine (the variables type, material, ID, unit, reading when hovered over are what they should be).
However, when the getData function is called below, when I hover over the pointer arguments(*type, *materials.. etc) they are set to random strings like directory names and file names. I'm not sure why this is happening, because when the variables are being set above they are right.
I've included the header and implementation files for the Data class, where all of these functions are defined, but If I need include where they are being called please let me know, the only reason I didn't is because the calls are short and files are filled with other irrelevant stuff. Thanks
Data.cpp
#include "Data.hpp"
Sensor::Sensor(char *DataType, char *Material, int ID, char *Sensor, double Min, double Max) {
strcpy(type, Type);
strcpy(material, Material);
ID = SIDs;
strcpy(unit, Units);
max = Maxs;
min = Mins;
}
Sensor::Sensor() {}
double Data::generateData() {
reading = min + (rand() % (int)(max - min + 1));
return reading;
}
void Data::getData(char *type, char *material, int *ID, char *unit, double *reading) {
return;
}
Data::~Data(){}
Data.hpp
#ifndef Data_hpp
#define Data_hpp
#include
#include
#include
using namespace std;
class Data
{
public:
Data();
Data(char *Type, char *Material, int ID, char *Unit, double Min, double Max);
~Data();
void getData(char *type, char *material, int *ID, char *unit, double *reading);
private:
char type[32];
char material[32];
int ID;
int reading;
char unit[32];
double min;
double max;
double generateData();
};
#endif
Your implementation of Sensor::getData does not do what you think it does.
Let's look at this class:
class Foo
{
void getX(int* x)
{
}
int* x;
};
Within getX, the parameter x hides the member x of the same name. This function does literally nothing: A user passes a pointer to an int, which gets the name x in this function. The member is not automatically copied into there (which would be surprising, since you could name the parameter anything else). If you want to do that, you must do it explicitly:
void getX(int* x)
{
*x = *this->x; // Pointed-to value is copied
//x = this->x; // Pointer is copied
}
If you do not set the function parameter to anything, the pointer will keep pointing to random garbage in memory, which is what you are seeing in your debugger.
The more common way to denote "this parameter will be changed/set by this function" is passing a reference:
class Foo
{
void get(char*& x, int*& y, double& z)
{
x = this->x; // Now both parameter and member point to the same location.
y = this->y; // Now both parameter and member point to the same location.
z = this->z;
}
char x[32];
int* y;
double z;
};
Or, if you don't want to copy the pointers but the pointed-to values:
void get(char* x, int* y, double& z)
{
strcopy(x, this->x);
*y = *this->y;
z = this->z;
}
(PS: I recommend using std::string instead of char arrays if your use case allows for it.)
You uninitialized arguments are set to random garbage no matter if you call getData() or not. Try to print them out without calling getData() and see.

C++ call method on object with the object itself as parameter

In python you can, for example, call array.sort() and it will sort the array it is called on. However, I now have the following code snippet
void drawClickableRectangle(ClickableRectangle recto){
ofSetHexColor(0xffffff); // just some syntax from the library I'm using
ofFill();
ofDrawRectangle(recto.xpos, recto.ypos, recto.width, recto.height);
}
and then call this method here:
ClickableRectangle recto(1,1,100,100);
recto.drawClickableRectangle(recto);
This is the full class:
class ClickableRectangle
{
// Access specifier
public:
// Data Members
int xpos, ypos, width, height;
ClickableRectangle(int x1, int y1, int width1, int height1){
xpos = x1;
ypos = y1;
width = width1;
height = height1;
};
// Member Functions()
int getxpos()
{
return xpos;
}
int getypos(){
return ypos;
}
int getwidth(){
return width;
}
void drawClickableRectangle(ClickableRectangle recto){
ofSetHexColor(0xffffff);
ofFill();
ofRect(recto.xpos,recto.ypos, recto.width, recto.height);
//ofDrawRectangle(recto.xpos, recto.ypos, recto.width, recto.height);
}
Is there a way to make the function call "reflexive"? So I can just call it like:
recto.drawClickableRectange();
I'm relatively new to C++, but not to programming in general. Thanks!
You can do like this in C++:
class ClickableRectangle {
public int xpos;
public int ypos;
public int width;
public int height;
void drawClickableRectangle(){
ofSetHexColor(0xffffff); // just some syntax from the library I'm using
ofFill();
ofDrawRectangle(xpos, ypos, width, height);
}
}
Then in your main function, call it like this:
int main(){
ClickableRectangle recto;
recto.xpos = 1;
recto.ypos = 1;
recto.width = 100;
recto.height = 100;
recto.drawClickableRectange();
return 0;
}
Not in the same way as python, no.
In python, you can
def unattached(fake_self):
return fake_self.x
class Thing:
def __init__(self):
self.x = 42
Thing.method = unattached
thing = Thing()
print (thing.method())
print (unattached(thing))
Because there's no difference between a free function with an explicit first paramter and a instance method with an implicit first parameter.
In C++, you can't change a class at runtime, and a member function has a different type to a free function.
struct Thing {
int x = 42;
int method() const { return this->x; }
}
int unattached(const Thing * thing) { return thing->x; }
The type of unattached is int (*)(const Thing *), whereas method is a int (const Thing::*)(). These are different types, you can't switch one for the other. You can however construct a std::function<int(const Thing *)> from either of them, but you can only use that with the free function syntax func(thing), as it isn't a member of Thing

Constructor in implementation versus header

The constructor should, to my knowledge, be defined in the implementation file but I've only been able to find examples with the class inside one main file instead of split into a .h and .cpp file
All I need to know is if my following code is separated in an acceptable manner..
Entity.h:
using namespace std;
class cEntity {
private:
/*-----------------------------
----------Init Methods---------
-----------------------------*/
int *X, *Y;
int *Height, *Width;
public:
/*-----------------------------
----------Constructor----------
-----------------------------*/
cEntity (int,int, int, int);
/*-----------------------------
----------Destructor-----------
-----------------------------*/
~cEntity ();
/*-----------------------------
----------Set Methods----------
-----------------------------*/
/*Set X,Y Methods*/
void setX(int x){*X=x;};
void setY(int y){*Y=y;};
void setXY(int x, int y){*X=x; *Y=y;};
/*Set Height, Width Methods*/
void setHeight(int x){*Height=x;};
void setWidth(int x){*Width=x;};
void setDimensions(int x, int y){*Height=x; *Width=y;};
/*-----------------------------
----------Get Methods----------
-----------------------------*/
/*Get X,Y Methods*/
int getX(){return *X;};
int getY(){return *Y;};
/*Get Height, Width Methods*/
int getHeight(){return *Height;};
int getWidth(){return *Width;};
};
and Entity.cpp:
#include "Entity.h"
cEntity::cEntity (int x, int y, int height, int width) {
X,Y,Height,Width = new int;
*X = x;
*Y = y;
*Height = height;
*Width = width;
}
cEntity::~cEntity () {
delete X, Y, Height, Width;
}
I would also like to say thanks to everyone for being so helpful, especially on my first question!
cEntity::cEntity (int x, int y, int height, int width) {
is correct
X,Y,Height,Width = new int;
not so much. That sets Width to a new int, but not the rest. You probably intended:
X = new int(x);
Y = new int(y);
Height = new int(height);
Width = new int(width);
Note that this method of construction will not work for objects without assignment/copy, like references. For some objects, it's also slower than constructing them in place. As such, the preferred way to construct is like so:
cEntity::cEntity (int x, int y, int height, int width) {
:X(new int(x))
,Y(new int(y))
,Height(new int(height))
,Width(new int(width))
{}
This is better, but if any exceptions are thrown, you'll have to somehow deallocate the ones that were allocated. Better is to make each of those members a std::unique_ptr<int>, so they'll deallocate themselves and save you many headaches.
Yes, it's OK.
However, there is a problem with your constructor and destructor.
What your code actually does is allocating one int and your destructor deallocates one int also.
Anyway, there is no need to use pointers here.
Somewhat better implementation (if we don't use smart pointers), could be:
[Entity.h]
private:
/*Private fields*/
int X, Y;
int Height, Width;
[Entity.cpp]
cEntity::cEntity (int x, int y, int height, int width) {
X = x;
Y = y;
Height = height;
Width = width;
}
cEntity::~cEntity () {
}
And one more thing. Try to avoid using namespace std; in your header files. If you do, you force those who include your header to use this using statement and it can provoke namespace clashes.
Your separation is fine. The implementations of those functions is wrong, but you've separated them from the declaration suitably. (They don't allocate or free as many objects as you think they do.)
Yes. For the separation at least, that's generally the best way to do it.
As for the actual implementation you have some issues. I am not really sure what you are trying to do with the constructor or if you have the correct data types for the class member variables but something seems off.
Any method defined in the class directly is implicitly inlined, including the constructor.
I.e.
class MyClass
{
public:
MyClass() {};
};
defines an inline constructor, which may (or may not) improve your code performance,
Whereas
class MyClass
{
public:
MyClass();
};
MyClass::MyClass()
{
};
is not inlined, and therefore won't have those benefits. Both options are correct C++ though.
Just my 2 cents.
P.S And yes, when you decide to store pointers inside a class in this manner, you open a Pandora box.