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;
}
Related
Let's say I have this simple class with a const int member variable:
class MyClass{
public:
Myclass(int x, int y);
private:
const int importantNumber;
int anotherNumber;
};
MyClass::MyClass(int x, int y) :importantNumber{x}
{
this->anotherNumber = y;
}
Since int importantNumber is const, I can only set it during the creation of the object by the constructor (with a member initialization list, as seen above).
Now, the question: how could I possibly add validation for argument x given to the constructor before actually creating importantNumber with that value? Is it possible to create a static int MyClass::validation(int a) and use it on the member initialization list of the constructor like importantNumber{validation(x)}?
Even if it's possible, is there a better way to do it?
You just add it.
MyClass::MyClass(int x, int y) : importantNumber{validate(x)}
{
this->anotherNumber = y;
}
The int validate(int original) function can now return something other than x or throw an exception or assert or ask the user for confirmation, whichever you deem appropriate.
If it is just a simple check and you don't want to write a validate function you can use a lambda:
MyClass::MyClass(int x, int y) :importantNumber{
[](int number){
assert(number > 0);
return number;
}(x)}
{
this->anotherNumber = y;
}
Although this can get a bit convoluted if you overdo it.
You can use the ternary operator condition ? true : false in the constructor if you want to validate with a simple condition:
class MyClass{
public:
MyClass(int x, int y);
private:
const int importantNumber;
int anotherNumber;
};
MyClass::MyClass(int x, int y) : importantNumber(x > 0 ? x : 0)
{
this->anotherNumber = y;
}
However, be warned that things can quickly become difficult to read if you overdo it with this operator.
For something more complex, you could do something like this:
int validateIntegral(int x) const
{
// Do validation on 'x'...
return x;
}
class MyClass{
public:
MyClass(int x, int y);
private:
const int importantNumber;
int anotherNumber;
};
MyClass::MyClass(int x, int y) : importantNumber(validateIntegral(x))
{
this->anotherNumber = y;
}
Use factory function for creating a class instead of constructor.
class MyClass
{
public:
static MyClass* create (int x, int y);
private:
MyClass(int x, int y);
private:
const int importantNumber;
int anotherNumber;
};
MyClass* MyClass::create (int x, int y)
{
return x > 0 ? new MyClass(x, y) : NULL;
}
When you need some advanced validation of parameters, factories have following advantages:
They avoid creation of object in memory if tests fail
They have more flexibility over checking parameters in initialization
list
You can return NULL if you dont need exceptions nor you want to have some ".is_valid()" member function for your class.
I want to have a class which has a member array. The size of the array should be given when I initialize the object. I just found a way with pointers to do this. I think it is working correctly, but can you maybe tell me if this is the best way to do it or if there are any things which do not work which I haven't recognized yet?
#include <iostream>
using namespace std;
class Surface {
private:
float dx;
int N;
float* mesh_points;
public:
Surface(float, int);
~Surface();
void set_dx (float);
float get_dx();
};
Surface::Surface(float dx,int N){
this->dx = dx;
this ->N = N;
mesh_points = new float[N];
}
void Surface::set_dx (float dx) {
this->dx = dx;
}
float Surface::get_dx (void) {
return dx;
}
Surface::~Surface(){
delete[] mesh_points;
}
int main () {
Surface s(1.2,10);
s.set_dx (3.3);
cout << "dx: "<< s.get_dx() <<endl;
float mesh_points[3];
return 0;
}
can you maybe tell me if this is the best way to do it or if there are any things which do not work which I haven't recognized yet?
That'd be my take basing on existing best practices:
class Surface {
private:
std::vector<float> mesh_points;
public:
float dx;
Surface(float dx, std::size_t n);
};
Surface::Surface(float dx, std::size_t n)
: dx(dx)
, mesh_points(n)
{
}
In short, the changes made:
Got rid of manual memory management, which implies dtor as well.
Added names for parameters in declarations (really important for usability/IDEs, don't remove them!)
Got rid of superfluous accessors and made dx public.
Used ctor init lists, making the body obsolete.
Got rid of using namespace std; in lieu of explicit std:: prefix.
Changed n type to std::size_t (see comment).
Please note that the current interface doesn't allow any access to mesh_points.
Here's an alternative suggestion that allows you to keep your current implementation but is a lot safer.
class Surface {
private:
float dx;
int N;
float* mesh_points;
public:
Surface(float, int);
~Surface();
void set_dx (float);
float get_dx();
Surface(const Surface&) = delete; // new
Surface& operator=(const Surface&) = delete; // new
};
By deleting the implementation of the copy constructor and copy assignment operator you prevent your Surface objects from being copied (which would likely crash your program anyway). Any attempt to copy Surface objects will now result in a compile time error.
Only a suggestion, my first choice would always be to use std::vector.
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);
I am trying to create a class that use the operator [] like
MyClass[x][y]
and it should return a value based on what I call in the function that is defined within the class. What I have so far is:
MyClass.h
class MyClass{
public:
// return one value of the matrix
friend double operator[][] (const int x, const int y);
}
I don't even think my syntax for this is right, and how can I write this function in MyClass.cpp to define what value it should return?
Like is it:
MyClass::friend double operator[][] (const int x, const int y)
{
// insert code here
}
Tried it but it keeps saying errors. I believe it is a mess up there...
Many thanks,
Overloading operator() is definitely the cleanest approach.
However, remember that this is C++, and you can bend the syntax to your will :)
In particular, if you insist on wanting to use myclass[][], you can do so by declaring an "intermediate class", here's an example:
Run It Online
#include <iostream>
using std::cout;
using std::endl;
class MyClass {
public:
using IndexType = int;
using ReturnType = double;
// intermediate structure
struct YClass {
MyClass& myclass;
IndexType x;
YClass (MyClass& c, IndexType x_) : myclass(c), x(x_) {}
ReturnType operator[](IndexType y_) { return myclass.compute(x, y_); }
};
// return an intermediate structure on which you can use opearator[]
YClass operator[](IndexType x) { return {*this, x}; }
// actual computation, called by the last "intremediate" class
ReturnType compute(IndexType x, IndexType y) {
return x * y;
}
};
int main()
{
MyClass myclass;
cout << myclass[2][3] << endl; // same as: cout << myclass.compute(2, 3) << endl;
}
You need to return a proxy object for the row. This is a very simplified example just to get you going. I have not tried compiling it.
class Matrix {
int data[4][4];
class Row {
Matrix* matrix;
int row;
int operator[](int index){
return matrix->data[row][index]; // Probably you want to check the index is in range here.
}
}
Row operator[](int row){
Row which_row;
which_row.matrix = this;
which_row.row = row; // beware that if the user passes the row around it might point to invalid memory if Matrix is deleted.
return which_row;
}
}
You could also just return the row directly from operator[] and leave the second [] to be a direct array access. IMHO it is nice with the proxy object as it can do some checking on the index and possibly have other nice member functions.
There is no operator[][]. But you can declare operator()(int, int) instead.
class Foo {
public:
double operator()(int a, int b) {
//...
}
};
If you're trying to create 4x4 Matrix class, the way I did it and the way its done in the D3DX library is to have a member variable in the class:
class Matrix
{
public:
// publicly accessible member 4x4 array
float m[4][4];
// also accessible via () operator. E.G. float value = mtx(3,2);
float operator()(int column, int row);
}
Related question: std::map default value for build-in type -- the subtle difference is I want more than to know whether the value is initialized to 0 or garbage, I want to specify a "constructor". I don't even care if it involves overhead with a class definition, I just want a clean "special" basic type. Even a syntactical hack would do. A non basic type is very easy to do this for, it is the entire job of the constructor.
I'd like to have a hashmap unordered_map<void *, int> but to have all its values default-initialized to -1 instead of 0 or garbage. This is because zero is a valid index, and I would prefer to default-initialize with a certainly invalid value.
I think I see a few sloppy ways this might be done with:
struct minus1 {
int i;
minus1() i(-1) {}
};
unordered_map<void*, minus1>
But I don't like this because I have to use .i to access the int, and it really just needs to be an int.
Okay so maybe I can have my map handle this:
struct PointerToIDHash {
std::unordered_map<void *, int> h;
PointerToIDHash() {
// ctor is powerless to affect the initialized values of future insertions into h
}
};
Well, crap now I have a .h too. Uhhhh. Can I inherit from a template? (sounds scary, but this might be a clean way if it can be pulled off)
How can I make a type that transparently acts like an int but is always initialized to -1?
I would prefer to know both how to do this with and without C++11.
#include <unordered_map>
#include <iostream>
using namespace std;
template<typename T, T default_value>
class SelfInitializer
{
public:
SelfInitializer(T x = default_value) : x(x) {}
operator T&() { return x; }
operator const T&() const { return x; }
private:
T x;
};
// demo
int main()
{
using minus1 = SelfInitializer<int, -1>;
unordered_map<int, minus1> m;
m[7] = 3; // assignment works
minus1 x = 3;
int y = x; // conversion to int works
int z = int(x); // explicit conversion works
cout << m[7] << endl;
}
add a conversion operator to int& so that your struct minus1 behaves like an int
struct minus1 {
int i;
minus1() : i(-1) {}
operator int&() { return i; }
};