Trouble with header files & c++ files - c++

I'm creating a minimal circle-circle physics engine in a static library, and I've came across a problem. I have a header file for object manipulation, one of the variables is the objects position. The position variable is declared in bpObject.h, and I have a void function, SetPosition(), that accesses the current position and sets its to the parameters specified (also declared in bpObject.h). My problem is that in the source file, I need to access the position variable (private). I can't access it through the bpObject class, because, being a class, it won't have the correct value when it is used as a type. So, how would I access the position variable within the class?
Thanks in advance,
Greg Treleaven
EDIT
Code for bpObject.h
#include "bpMath.h"
namespace bp
{
class Object
{
private:
static bp::Vector position;
static bp::Vector velocity;
static bp::Vector acceleration;
public:
static single restitution;
static single radius;
static void setPosition(single X, single Y);
static bp::Vector getPosition();
static void applyPosition(single X, single Y);
static void setVelocity(single X, single Y);
static bp::Vector getVelocity();
static void applyVelocity(single X, single Y);
static void setAcceleration(single X, single Y);
static bp::Vector getAcceleration();
static void applyAcceleration(single X, single Y);
}
}

I'm guessing you don't actually want all those 'static's in there, is your first problem (as it stands, you pretty much can only access a single object)
Once you get rid of those, you can implement SetPosition in your source file by:
namespace bp {
void Object::SetPosition(single X, single Y) {
position[0] = X; //or however your bp::Vector is implemented
position[1] = Y;
}
}
Yes, position is private, but when you actually define the method, you get to access the members. Is this at all what you are asking?

You're asking the wrong question. If, as you say, the variable doesn't have the correct value when it's needed, then the problem has nothing to do with access methods or public/private.
How is the variable supposed to get its proper value? Something must call setPosition, so you have to arrange things so that this happens before anything else needs that value.
Once you have that, your accessors (setPosition and getPosition) should work just fine (after you get rid of the static, which makes no sense).

Related

Creating a variable of an object type

I've been stuck on this problem and can't seem to get my head around it, I'm creating a program in C++ that calculates various functions such as area, perimeter, points of different shapes.
Part of this includes creating a leftTop variable of Point type (Point is a class that simply has 2 ints (x and y) and a method called Point to print out the x and y of different shapes). I've used a template to create a function of point type that simply returns x and y, I know this is incorrect but thought I'd try it anyway.
template <typename Point>
Point leftTop(Point x, Point y) {
return x, y;
}
But it needs to be a data member of point type (stored in a class called shape) that is used to store the x and y coordinates of the left top point of the shape and I'm stuck on how to implement this, as I need to use the leftTop variable to calculate the other points of the shape such as leftBottom, rightTop, etc.
You're making things over-complicated by using a templated function! The exact solution depends on how you have defined your Point class, but you probably just need a relevant constructor:
class Point
{
public
Point(int px, int py) : x{ px }, y{ py } {}
public: // Make these "private" if you want to prevent direct access
int x;
int y;
};
And then you can create your leftTop object very easily:
int left = 12; // Or whatever
int top = 17;
Point leftTop(left, top);
You can add other member functions to do pretty much anything else you'd care to.
As you're using Visual Studio, and thus may have access to the MFC classes, you could maybe take a look at how MFC implements its CPoint and CRect classes for guidance. If you can't get to see the MFC stuff, then the Windows.h file provides C-style structs called POINT and RECT that could also be helpful.

Class method being called in main, changes don't persist outside class method?

Basically, I have two classes, Peg and Disk. (It's a Towers of Hanoi program) The files I have are Disk.h, Disk.cpp, Peg.h, Peg.cpp, and main.cpp. Not sure if that matters. Here's the disk class from Disk.h
#include <vector>
#include "gwindow.h"
#ifndef DISK_H
#define DISK_H
class Disk
{
private:
int xCoord; //x and y coords are for drawing in a gwindow
int yCoord;
int mHeight;
int mWidth;
COLOR mColor;
int mName; //helps me keep track of which is which
public:
Disk(); //default constructor
Disk(int x, int y, int heightIn, int widthIn, COLOR colorIn);
void setXY(int x, int y); //this is the one I'm having trouble with
int getHeight();
int getWidth();
int getX();
int getY();
COLOR getColor();
std::string diskColor();
void draw(GWindow &gw);
void nameDisk(int name); //yet this one is working?
int getName();
};
#endif
However, I'm having trouble with the setXY function. When I call it from main, it calls the function properly, changes the variable inside the scope of setXY, but the value doesn't persist outside the function. However, nameDisk works fine and is basically the same thing, except it is changing mName instead of xCoord and yCoord. Here is setXY:
void Disk::setXY(int x, int y)
{
xCoord = x;
yCoord= y;
}
and here is how I call it from main:
pegVec[2].getDisks()[0].setXY(690, 200);
I know this looks crazy, but basically pegVec is a vector of 3 peg objects. Each peg object has a function, getDisks(), which returns a vector of all the disks on that peg currently. So the line above is trying to perform setXY on the first peg on peg 2. Sorry if that's unclear, but I've tried making a new disk object and calling it on that and that didn't work either.
Here is getDisks, if it matters:
std::vector<Disk> Peg::getDisks()
{
return disksOn;
}
and disksOn is just a member variable of Peg:
std::vector<Disk> disksOn;
I think it might be a problem with how getDisks() works. I'm a noob, but I'm guessing that returning the vector disksOn makes a "copy" of it, kind of, which is what I am altering with my setXY function but which is not the same as the actual disksOn vector associated with the Peg object? I don't know if that makes sense.
What I've tried so far:
Making xCoord and yCoord public variables and updating them manually instead of making a setter function. This did not work.
I printed out the x and y values at every step. Inside setXY, the values were updated successfully, but when the function ended they went back to how they were.
I tried some mess with the const keyword, but I don't understand it and couldn't even get it to run.
Passing everything by reference/value
Making a new function in main which accepted a Disk vector as input, and using getDisks as input to that function. Didn't work, same problems.
Tested my other setter function, nameDisk, which works fine. It's essentially the same as setXY, which is why I think the problem is with getDisks.
Using pointers at various points (heh) throughout, but I wasn't sure the best way to do that. I was messing with it last night so I don't remember 100% but I think I tried to have getDisks return a pointer instead of the vector, and I don't think that worked, but it's more likely a problem with my syntax and how I used the pointer. I think that might work but I don't know how to shake it.
Help?
You're on the right track - somehow you're looking at a different objects than what you think you are. Using references is a good solution, but you may not have got the right one ;-)
Try:
// Return reference to the disks on the peg.
std::vector<Disk>& Peg::getDisks()
{
return disksOn;
}
The issue is that
std::vector<Disk> getDisks() { return disksOn; }
returns a completely new and separate temporary copy of disksOn rather than a reference to the original. So you're modifying a temporary copy which gets discarded at the end of the statement.
You need to use
std::vector<Disk> &getDisks() { return disksOn; } in order to return a reference to disksOn.
Although if you are going to return a reference to the vector member object you might as well make the object directly accessible as public because anyone can manipulate the vector at this point and get rid of the getDisks() function as it serves no purpose in terms of access protection.
Better design would be to give access to individual disks:
Disk &getDisk(int index) {
return disksOn[index];
}
const Disk &getDisk(int index) const {
return disksOn[index];
}
The idea behind not giving direct access to the vector is that you can later change the underlying container type if needed without changing the code outside of the Peg class.
The second version (const) is necessary for accessing const Disks of const Peg objects.

How can I initialize class variables in a header?

I'm writing a library where the user can define arbitrary structures and pass them to my library, which will then obtain the memory layout of the structure from a static member such structure must have as a convention.
For example:
struct CubeVertex {
// This is, per convention, required in each structure to describe itself
static const VertexElement Elements[];
float x, y, z;
float u, v;
};
const VertexElement CubeVertex::Elements[] = {
VertexElement("Position", VertexElementType::Float3),
VertexElement("TextureCoordinates", VertexElementType::Float2),
};
C++ best practices would suggest that I move the static variable and its initialization into my source (.cpp) file. I, however, want to keep the variable initialization as close to the structure as possible since whenever the structure changes, the variable has to be updated as well.
Is there a portable (= MSVC + GCC at least) way to declare such a variable inside the header file without causing ambiguous symbol / redefinition errors from the linker?
Consider a simple getter.
struct CubeVertex {
static const std::array<VertexElement, N>& GetElements() {
static const std::array<VertexElement, N> result = {
//..
};
return result;
}
//..
}
Immediate benefit: No array-to-pointer-decay.
What you could do here is using an anonymous namespace.
Wrap everything into "namespace { ... };" and you can then access CubeVertex::Elements like you normally do.
However, this creates a new instance of the static data everytime you include the headerfile, which adds to the executable's filesize.
It also has some limitations on how to use the class/struct, because you cannot call functions of that class from another file (which won't be a problem in this special case here).

Global variable in C++

I'm writing c++ project, which contains several classes. I created .h file named Position.h, with one array and one function:
class Position
{
public:
Coord positions[25];
public:
void setPos(int index, double x, double y)
{
positions[index].x = x;
positions[index].y = y;
}
};
I want to set values in this array from another classes, so every class in this project will see the same values.
I included "Position.h" in other classes, but i can't access the "positions" array.
Anyone can help me plz??
Just chnage the statement :
Coord positions[25];
to
static Coord positions[25];
also change void setPos
to
static void setPos
while accesing the array ,access it as:
Position::positions[any value]
But before accessing the array,make sure you call the function setPos
positions is a member variable associated with a class instance, and therefore not a global. You can make it similar to a global by making it static. Doing so, it will become a class-scoped variable, and not bound to an instance.
You will need to define it in a single implementation file.
An even better alternative would be having an std::vector<Coord>.
As suggested by others, you can make the members static.
You can also create an instance of the Position class as a global variable, and use that:
Position globalPosition;
void function_using_position()
{
globalPosition.setPos(0, 1, 2);
}
int main()
{
function_using_position();
}
Or make it a local variable, and pass it around as a reference:
void function_using_position(Position &position)
{
position.setPos(0, 1, 2);
}
int main()
{
Position localPosition;
function_using_position(localPosition);
}

Accessing a method of a member object in C++

I am trying to access a method of an object (myEOS.calc(...)) from a method of an object (myPlanet) of another class containing an instance of the first class (static EOS myEOS):
// class in class
class EOS {
public:
static float Y;
float calc(float);
};
float EOS::calc(float x){
return x; // some complicated calculation
}
class Planet {
public:
static EOS myEOS; // want only one instance; cf. below
static void setX(float* X); // must be static; cf. below
};
void Planet::setX(float* X) {
*X = myEOS.calc(*X); // will give an error
}
int main(){
Planet myPlanet;
}
This returns the linking-time error
In function `Planet::setX(float*)':
test.cpp:(.text+0x1a): undefined reference to `Planet::myEOS'
collect2: ld returned 1 exit status
Compiling separately, with -c, the classes and the main program (with an #include in the main file) gives no error; this looks like the key to the solution but I do not see the lock!
Does someone know what the problem is? I hope my intent is clear from what I have, even if there is some fundamental misconception. I thought I somewhat understood classes and reread tutorials but saw no discussion of classes within classes (not nested classes). I was not able to find a similar question on this site (from which I can usually get all the answers I need!) either.
By the way, following somebody else's question, adding explicit constructors (and correctly initialising the EOS in Planet's initialiser list) did not remove the compiler complaint about "undefined reference to Planet::myEOS'" (this done without thestatic` keyword).
Finally, note that Planet::setX needs to be static because a pointer to this method must have a "class-less" signature as it is passed to a function that cannot handle methods/classes:
void (*fun_ptr)(float*) = & (Planet::setX);
This also forces the object myEOS to be static (needs to be accessed from a static function), and anyway the initialisation of EOS objects is expensive.
Thanks a lot for anybody's help!
class Planet {
public:
static EOS myEOS; // want only one instance; cf. below
This code says "Compiler: Somewhere later will be a global EOS myEOS for this class. And the compiler says "ok", and does it's thing, waiting for you to tell it where the global EOS myEOS is.
Then the linker comes along to clean up the compiler's mess, and says "I can't find the myEOS, where'd you place the myEOS?" And displays an error.
You need to add the following lines to a CPP file somewhere:
float EOS::Y;
EOS Planet::myEOS;
Define the static variable.
// class in class
class EOS {
public:
static float Y;
float calc(float);
};
float EOS::calc(float x){
return x; // some complicated calculation
}
class Planet {
public:
static EOS myEOS; // want only one instance; cf. below
static void setX(float* X); // must be static; cf. below
};
void Planet::setX(float* X) {
*X = myEOS.calc(*X); // will give an error
}
// -------------------------
EOS Planet::myEOS;
float Planet::Y /* = <some value> if it makes sense*/;
// -------------------------
int main(){
Planet myPlanet;
}
See 9.4.2 Static Data Members in the standard (98).