C++ Circular declaration - c++

I have a couple of cases of circular declaration in my class delaractions in my main (global) header.
#include <cstdlib>
#include <iostream>
using namespace std;
enum piece_t {BLACK, WHITE, EMPTY, WALL}; //wall is area out side of board (board array is 21x21 but only 19x19 is playable)
enum dir_t {ABOVE,BELOW,LEFT, RIGHT}; //shall i overload ! or - operatior? !LEFT==RIGHT?
struct nextPoint_t //should be implimented with references, but need to practice pointer
{
point_t* above;
point_t* below;
point_t* left;
point_t* right;
};
class point_t
{
private:
piece_t mType; //what sort of point this is
int mLiberties;
nextPoint_t mAdjacent; // points to adjacent points
bool mLibertiesCounted; // keeps track of if liberties have been counted, for mCountLiberites() (sets), is reset by mUpdateLiberites();
int mCountLiberties(); //counts this point's liberites, by calling count on mAdjacent points etc.
void mSetPos(int xPos, int yPos, board_t theBoard); //sets up mAdjacent to point to adjacent points,
void mSetStructureLiberties(int numLibs); // Sets this squares liberites then calls this on all adjacent squares
public:
point_t ();// parameterless constructor, for arrays
void mSetUp(int xPos, int yPos, board_t theBoard);// sets up mType then calles setPos iFF not WALL type
point_t (int xPos, int yPos, board_t theBoard); //constructor, takes it's position in the grid as a parameter
void mUpdateLiberties(); // calles countLiberties then, updates liberites on whole of connected structure, by operating pon all conencted points
};
class board_t
{
private:
point_t mArray [21][21];
public:
board_t(); //constructor, sets up board by operating on the point_t's
};
Don't worry about the comments there for my reading, I know what I mean.
I thought I could fix it with forward declarations, but they don't seem to work, it just thinks I'm redeifining the classes

Alright, after considering the comments and doing a test on my own, the real answer :
You must use forward declaration, no more. :)
#include <cstdlib>
#include <iostream>
class point_t;
class board_t;
/* Rest of the code stay the same */

The forward references in your code seems to be to board_t and point_t, which is resolved by forward declaring them.
Since you reference board_t in member function declarations of point_t, you cannot define the member functions right away in point_t. Their definitions have to appear after board_t is defined. So you have to either move the definition of the functions into the cpp file, or you have to move their definition in the header after definition of board_t whichever suites you more. point_t is only used as a pointee type in nextPoint_t, so we don't have the same problem for it here:
class point_t; // used by nextPoint_t
class board_t; // used by point_t
struct nextPoint_t //should be implimented with references, but need to practice pointer
{
point_t* above; // goes without problems - doesn't need definition of point_t
point_t* below;
point_t* left;
point_t* right;
};
class point_t
{
private:
piece_t mType;
int mLiberties;
nextPoint_t mAdjacent;
bool mLibertiesCounted;
int mCountLiberties();
void mSetPos(int xPos, int yPos, board_t theBoard);
void mSetStructureLiberties(int numLibs);
public:
point_t ();
void mSetUp(int xPos, int yPos, board_t theBoard);
point_t (int xPos, int yPos, board_t theBoard);
void mUpdateLiberties();
};
class board_t
{
private:
point_t mArray [21][21];
public:
board_t();
};
Definition at the end of the header looks like
// define it either inline in the header, or non-inline in a cpp file
inline void point_t::mSetPos(int xPos, int yPos, board_t theBoard) {
/* some work... */
}
// same for mSetUp...
Nonetheless i would recommend you to use const references to pass the board to point_t's member functions, but this is not a requirement for your code to work. Declarations go fine with incomplete parameter types.

if you write before your struct
class point_t;
that should do the trick.
Although I am not quite sure why your organize your class like that. You already have an array mArray in your board so there is no real need to have pointers to adjacent points inside each point_t.
EDIT: as the other poster said before you need to use pointers.

Just add this above struct nextPoint_t
enum piece_t {BLACK, WHITE, EMPTY, WALL};
enum dir_t {ABOVE,BELOW,LEFT, RIGHT};
class point_t;
class board_t;
struct nextPoint_t
{
point_t* above;
point_t* below;
point_t* left;
point_t* right;
};
And change any reference to a board_t to a board_t*
void mSetUp(int xPos, int yPos, board_t* theBoard);

#include <cstdlib>
#include <iostream>
enum piece_t {BLACK, WHITE, EMPTY, WALL}; //wall is area out side of board (board array is 21x21 but only 19x19 is playable)
enum dir_t {ABOVE,BELOW,LEFT, RIGHT}; //shall i overload ! or - operatior? !LEFT==RIGHT?
class point_t;
struct nextPoint_t //should be implimented with references, but need to practice pointer
{
point_t* above;
point_t* below;
point_t* left;
point_t* right;
};
class board_t;
class point_t
{
private:
piece_t mType; //what sort of point this is
int mLiberties;
nextPoint_t mAdjacent; // points to adjacent points
bool mLibertiesCounted; // keeps track of if liberties have been counted, for mCountLiberites() (sets), is reset by mUpdateLiberites();
int mCountLiberties(); //counts this point's liberites, by calling count on mAdjacent points etc.
void mSetPos(int xPos, int yPos, const board_&t theBoard); //sets up mAdjacent to point to adjacent points,
void mSetStructureLiberties(int numLibs); // Sets this squares liberites then calls this on all adjacent squares
public:
point_t ();// parameterless constructor, for arrays
void mSetUp(int xPos, int yPos, const board_t& theBoard);// sets up mType then calles setPos iFF not WALL type
point_t (int xPos, int yPos, const board_t& theBoard); //constructor, takes it's position in the grid as a parameter
void mUpdateLiberties(); // calles countLiberties then, updates liberites on whole of connected structure, by operating pon all conencted points
};
class board_t
{
private:
point_t mArray [21][21];
public:
board_t(); //constructor, sets up board by operating on the point_t's
};

Related

Store cursor position in class object (ncurses 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);

C++: copyable view on an object

I'm trying to make a program that deals with images, in which I have an image object and an image_view object that references a rectangle region in the image:
class image_view;
class image
{
public:
image(int width, int height);
operator image_view() const;
private:
int m_width;
int m_height;
std::vector<pixel> m_pixels;
};
class image_view
{
public:
image_view(const image& ref, point origin, int width, int height);
image_view(image_view view, point origin, int width, int height);
private:
const image& m_ref;
point m_origin;
int m_width;
int m_height;
};
However, when I tried to copy an image_view, the compiler told me that the operator= member function had been deleted because of the non-static member reference. I naively tried to make my own member function with m_ref = other.m_ref but it didn't work since m_ref is const.
I considered using a smart pointer instead of a reference, but I didn't find a way of making a smart pointer to an already existing object.
One solution I found is the following:
image_view& image_view::operator= (const image_view& other)
{
*this = image_view(other);
return *this;
}
This compiles, but is it a good idea? (I might be wrong, but I feel bad about assigning stuff to *this.) If I do that, does that mean I have to define a destructor (even though I'm not allocating anything), move constructor and move assignment operator to satisfy the rule of 5?
If you want to express a non-owning, non-null wrapper that rebinds on assignment, the easiest way to do that is to use std::reference_wrapper:
class image_view
{
public:
image_view(const image& ref, point origin, int width, int height);
image_view(image_view view, point origin, int width, int height);
private:
std::reference_wrapper<image const> m_ref;
point m_origin;
int m_width;
int m_height;
};
The default copy constructor and assignment operator will do the right thing.

How to workaround "redefinition of default parameter" in class constructor

Consider the following example:
class Rectangle{
Rectangle(int x, int y, int width, int height);
Rectangle(int topLeft_x, int topLeft_y, int bottomRight_x, int bottomRight_y);
};
A Rectangle object may be built giving (x,y) coordinates plus width and height or giving top left points pair and bottom right points pair.
While this is correct from an object oriented point of view, this is not from a compiler point of view, returning the error "member function already defined or declared"
While I normally fix this condition easily in case of member function, simply changing the name according to what it does, this is not possible for constructors.
What is the simpler and correct way to workaround this issue keeping both the way to construct the object?
Another possible solution (other than the pair suggested by #VladfromMoscow) is a static method to perform construction. This lets you give them distinct names, since their argument lists are so similar. Thisi is called the Named Constructor Idiom
class Rectangle
{
public:
static Rectangle createRectangle(int x, int y, int width, int height)
{
return Rectangle(x,y,width,height);
}
static Rectangle createRectangleCorners(int x1, int y1, int x2, int y2)
{
return Rectangle(x1,y1,x2-x1, y2-y1);
}
private:
// Doesn't have to be private, but this forces users to use the above
// constructors
Rectangle(int x, int y, int width, int height);
}
You wrote already yourself
top left points pair and bottom right points pair
So what you need is to define class Point and use this type in the constructor declaration.
Otherwise the constructors are declared like
class Rectangle{
Rectangle(int, int, int, int);
Rectangle(int, int, int, int);
};
As you see these declarations do not make sense even if you will write multiline comments.:)
Another approach is to declare the first constructor like
class Rectangle{
Rectangle(int x, int y, unsigned int width, unsigned int height);
Rectangle(int topLeft_x, int topLeft_y, int bottomRight_x, int bottomRight_y);
};
However this approach is unsafe because each integer literal specified as the third or fourth argument must be casted.
Instead of the class Point you could use standard class std::pair. For example
#include <utility>
//...
class Rectangle{
Rectangle(int x, int y, int width, int height);
Rectangle( const std::pair<int, int> &topLeft, const std::pair<int, int> &bottomRight);
};
Another way on how to solve this problem is by using Tag dispatching:
Instead of using methods with different names, give them a new parameter, e.g.,
struct useCorners {};
struct useDimension {};
class Rectangle
{
Rectangle(useCorners, int topLeft, int topRight, int bottomLeft, int bottomRight)
{ ...
}
Rectangle(useDimension, int topLeft, int topRight, int width, int height)
{ ...
}
};

Copy Constructor Pointer Object

I have the following class with the 2 pointers to block
#ifndef SCORING_H
#define SCORING_H
#include "Block.h"
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
class Scoring
{
public:
Scoring(Block *, Block*, string, string, double);
virtual ~Scoring();
Scoring(const Block& b1, const Block &b2);
private:
Block * b1;
Block * b2;
string path1;
string path2;
double val;
};
#endif // SCORING_H
Class Block is the following:
class Block {
public :
///constructo
Block(double, double, double, double, int, vector<LineElement*>);
///Setter functions
void setID(int);
void setTop(double);
void setLeft(double);
void setRight(double);
void setBottom(double);
void setLine(vector<LineElement*>);
int getID();
double getTop();
double getLeft();
double getBottom();
double getRight();
vector<LineElement*> getLine();
private:
int id;
vector<LineElement*> Listline;
double top;
double left;
double bottom;
double right;
};
#endif // ELEMENT_H_INCLUDED
I want to know, Should I construct a copy constructor for "Block * b1;Block * b2" and how can I treat these 2 points in the class scoring.h?
Thank you.
If you create a constructor other than plain and simple Block::Block(const Block&) then it's not a copy-constructor. If you want to make a constructor in Scoring taking two Block pointers it's most definitely is not a copy-constructor.
If you want a copy-constructor in Scoring it should be like this:
class Scoring
{
// ...
Scoring(const Scoring& other);
// ...
};
Then in that constructor you copy from other:
Scoring::Scoring(const Scoring& other)
: b1(new Block(*other.b1)),
b2(new Block(*other.b2)),
path1(other.path1),
path2(other.path2),
val(other.val)
{
}
Of course, you should probably make a copy-constructor for the Block class too, as it contains a vector of pointers, and if you don't you will have two vectors with pointers pointing to the same objects, and that will be bad when you delete these objects in one vector but not the other.

assign passed object to member object in constructor

for some reason I can´t achieve this.
Line::Line(const Pixel &aStart, const Pixel &aEnd){
start = aStart;
end = aEnd;
}
the Line class:
class Line : public Vertex{
public:
Line(const Pixel &start, const Pixel &end);
Pixel getStart();
Pixel getEnd();
private:
Pixel start;
Pixel end;
};
g++ tells me
error: no matching function for call to ‘Pixel::Pixel()’
note: candidates are:
- Pixel::Pixel(int, int, int, int, int)
- Pixel::Pixel(int, int)
- Pixel::Pixel(const Pixel&)//not implemented by me, some sort of default constructor?
I thought actually Im using the last constructor, but something doesnt work. Any help much appreciated.
EDIT: The Pixel Class:
class Pixel{
public:
Pixel(int x, int y);
Pixel(int red, int green, int blue, int x, int y);
void setRed(int red);
void setGreen(int green);
void setBlue(int blue);
void setColor(int r, int g, int b);
int getRed();
int getGreen();
int getBlue();
bool isChanged();
int getX();
int getY();
private:
int red;
int green;
int blue;
int x;
int y;
bool hasBeenChanged;
};
The Line members of type Pixel, start and end, will be default constructed before the constructor of Line runs and sets them to the objects passed in as arguments. It seems that your Pixel class doesn't have a default constructor (because giving any user-defined constructor will stop the compiler from giving you an implicit default constructor). You need to make use of a constructor member initialization list:
Line::Line(const Pixel &aStart, const Pixel &aEnd)
: start(aStart), end(aEnd)
{ }
This initialises start and end with aStart and aEnd respectively, bypassing the default construction that would normally occur.
Because you declare this
Pixel::Pixel(int, int, int, int, int)
Pixel::Pixel(int, int)
the compiler doesn't generate a default constrcutor, or a constructor exists with arguements having default values.
Pixel start;
Pixel end;
These require a default constructor. It doesn't find one, hence the compiler complains. You current code requires the default constructors.
And as a good practice use the initialization list, which wouldn't ask the arguements to default constructed.
Line::Line(const Pixel &aStart, const Pixel &aEnd):start(aStart), end(aEnd){}