I'm writing an open source project for the Xbox 360, it's my first time using C++ and I'm obviously doing something (Most likely many things) wrong.
My specific problem at the moment is that I create many instances of a class, passing in a reference to an object in the constructor, and setting a member variable to that object.
Later, when I access these objects, the member variable does not contain the object I assigned to it in the constructor.
Also, these objects have an Update(float x, float y) method, in this method I simply assign the x and y to member variables _x and _y.
When I access these values later, they are garbage.
I'm going to try post the relevant code here, but there may be something I miss, so just in case here is a link to the github project Github - Xenu.
The class I'm referring to is source/GUIApplicationPanel and the instantiating/using of them is in source/GUIManager.
Here is the object I am instantiating many instances of:
GUIApplicationPanel.H
class GUIApplicationPanel {
public:
GUIApplicationPanel(LibXenonApplication libXenonApplication);
void update(float x, float y);
void draw();
private:
LibXenonApplication application;
float _x, _y;
};
GUIApplicationPanel.CPP
GUIApplicationPanel::GUIApplicationPanel(LibXenonApplication libXenonApplication)
{
application = libXenonApplication;
}
void GUIApplicationPanel::update(float x, float y)
{
_x = x;
_y = y;
}
void GUIApplicationPanel::draw()
{
Draw::DrawColoredRect(_x, _y, 0.3f, 0.3f, ThemeManager::GetPanelColor());
}
And here is the code that creates them:
GUIManager.H
class GUIManager {
public:
void update(controller_data_s controller);
void draw();
private:
/* SNIP SNIP */
vector<GUIApplicationPanel> *currentPanels;
vector<GUIApplicationPanel> applicationPanels;
};
GUIManager.C
vector<LibXenonApplication> applications = LibXenonApplicationManager::GetApplications(applicationsPath);
// Create panels for applications
for(vector<LibXenonApplication>::iterator iter = applications.begin(); iter != applications.end(); ++iter) {
applicationPanels.push_back(GUIApplicationPanel(*iter));
}
Here is the code that updates them:
currentPanels = &applicationPanels;
// Render each screens worth of panels
for(int currentPass = 0; currentPass < renderPasses; currentPass++) {
horizontalOffset = currentPass * 1.0f;
for(int verticalPanel = 0; verticalPanel < verticalPanels; verticalPanel++) {
for(int horizontalPanel = 0; horizontalPanel < horizontalPanels; horizontalPanel++) {
// Make sure we haven't exceeded the amount of panels we're drawing...
if(panelIndex >= currentPanels->size()){break;}
// Get the panel at the current index
GUIApplicationPanel currentPanel = currentPanels->at(panelIndex);
// Calculate its position
float panelX = horizontalOffset + xStart + (horizontalPanel * panelWidth) + (horizontalPanel * panelGap);
float panelY = yStart + (verticalPanel * panelHeight) + (verticalPanel * panelGap);
// Update the panel
currentPanel.update(panelX, panelY);
// Move to the next panel...
panelIndex++;
}
}
}
And lastly here is the code that accesses values on them:
for(vector<GUIApplicationPanel>::iterator iter = currentPanels->begin(); iter != currentPanels->end(); ++iter) {
iter->draw();
}
To be honest I'm all out of ideas - Acessing the application variable on a panel anywhere other than the constructor results in it being garbage, and likewise with _x and _y (Other than in the update method).
I put some logging in, so a line will be开发者_运维问答 logged in the update method of the panel logging the values of _x and _y after they've been set, as well as showing the name of the application (Which comes out blank in the log).
A line will also be logged when the draw method is called showing the current values of _x, _y and application:
Updating to x -0.70 y 0.40
Updating to x -0.30 y 0.40
Updating to x 0.10 y 0.40
Updating to x 0.50 y 0.40
Updating to x 0.90 y 0.40
Updating to x -0.70 y 0.80
Updating to x -0.30 y 0.80
Updating to x 0.10 y 0.80
Updating to x 0.50 y 0.80
Drawing at x 0.00 y 0.00
Drawing at x 0.00 y 0.00
Drawing at x 0.00 y 0.00
Drawing at x 0.00 y 0.00
Drawing at x 0.00 y 0.00
Drawing at x 0.00 y 0.00
Drawing at x 0.00 y 0.00
Drawing at x 0.00 y 275577729171396449271808.00
Drawing at x 0.00 y 0.00
The problem lies in the way you access the elements in the vector:
GUIApplicationPanel currentPanel = currentPanels->at(panelIndex);
This obtains a copy of the element, so you set the attributes of the copy, not the item held in the container. Obtain a reference and then you can modify the item in the container..
EDIT: Based on comment, as you've realised std::vector<>::at()
return a reference, so what you need to do is change the above to be a reference, i.e.
GUIApplicationPanel& currentPanel = currentPanels->at(panelIndex);
Now currentPanel
refers to the instance of GUIApplicationPanel
at the specified index in the container.
Seems to me that the problem is with initialization. _x
and _y
are not initialized in the constructor of GUIApplicationPanel
, and may have arbitrary values. If, by chance, a panel is not updated, it will have that rare values.
EDIT:
As per your comment, another problem could be that you hold variables of type LibXenonApplication
and GUIapplicationPanel
by value. I suggest you to use pointers to hold references to those panels instead of copies of those objects. There may lay your errors.
精彩评论