Can't pass a string to my class function - c++

I have a class with this function:
void Render(SDL_Surface *source,SDL_Surface *destination,string img)
{
SDL_Rect offset;
offset.x = m_x;
offset.y = m_y;
source = IMG_Load(img);
offset.w = source->w;
offset.h = source->h;
}
For some reason though even with include <string> at the top of the header file it won't allow it. I get:
Identifier, "string" is undefined.
Im passing the data like this on my main file:
btn_quit.Render(menu,screen,"button.png");
When i execute i get :
'Button::Render' : function does not take 3 arguments
But this site says string is the correct syntax for the data type (at the bottom): http://www.cplusplus.com/doc/tutorial/variables/
Can some one explain what I am doing wrong ?

I may suggest you change Render function to below:
void Render(SDL_Surface *source,SDL_Surface *destination,const std::string& img)
{
SDL_Rect offset;
offset.x = m_x;
offset.y = m_y;
source = IMG_Load(img.c_str());
offset.w = source->w;
offset.h = source->h;
}
use std::string instead of string
pass img reference instead of passing by value
change from IMG_Load(img); to IMG_Load(img.c_str());

Related

VertexArray declaration inside a class

I'm trying to create a struct containing a point primitive and a method to draw it. However, declaration of a sf::VertexArray outside of method doesn't seem to work. The exactly same declaration inside a method works perfectly fine. Here are the code samples and the error. SFML version 2.1
edit: in both cases using namespace std; is used.
Works:
struct Point
{
int dot_x, dot_y;
sf::Color dot_color;
Point (int x = 50, int y = 50, sf::Color color = sf::Color::Green) {
dot_color = color;
dot_x = x;
dot_y = y;
}
virtual void draw() {
sf::VertexArray dot(sf::Points, 1);
dot[0].position = sf::Vector2f(dot_x,dot_y);
dot[0].color = dot_color;
window.draw(dot);
}
};
Does not work:
struct Point {
sf::VertexArray dot(sf::Points, 1);
Point (int x = 50, int y = 50, sf::Color color = sf::Color::Green) {
dot[0].position = sf::Vector2f(x,y);
dot[0].color = color;
}
virtual void draw() {
window.draw(dot);
}
};
Errors (all pointing at the VertexArray declaration string):
E:\CodeBlocks\Labs\sem3\sfml1\main.cpp|64|error: 'sf::Points' is not a type|
E:\CodeBlocks\Labs\sem3\sfml1\main.cpp|64|error: expected identifier before numeric constant|
E:\CodeBlocks\Labs\sem3\sfml1\main.cpp|64|error: expected ',' or '...' before numeric constant|
sf::VertexArray dot(sf::Points, 1);
This is a declaration of a variable with an initialiser: you can only write those at namespace or function scope. The parser is suitably confused, as you have it in your class scope. It's basically trying to parse it as a function declaration but, since neither sf::Points nor 1 are types, this approach ultimately fails also.
You should use the constructor's member initialiser list here:
struct Point
{
sf::VertexArray dot;
Point (int x = 50, int y = 50, sf::Color color = sf::Color::Green)
: dot(sf::Points, 1)
{
dot[0].position = sf::Vector2f(x,y);
dot[0].color = color;
}
virtual void draw()
{
window.draw(dot);
}
};

C++ returning class object through multiple function

I'm trying to pass custom object (TextureInfos) through multiples functions.
The call is:
TextureManager::Instance()->getTextureInfos("TEST",0)
TextureManager.cpp
TextureInfos& TextureManager::getTextureInfos(std::string key, int id)
{
TextureSet textureSet = textureSets[key];
return textureSet.getTextureInfos(id);
}
TextureSet .cpp
TextureInfos& TextureSet::getTextureInfos(int id)
{
sf::Texture texture;
sf::IntRect rect;
if (id < tileCount) {
int x = (id % maxCol) * tileWidth;
int y = (id / maxCol) * tileHeight;
rect.left = x;
rect.top = y;
rect.width = tileWidth;
rect.height = tileHeight;
}
TextureInfos *textureInfos = new TextureInfos(texture,rect);
return textureInfos;
}
I'm new to C++ and I think I miss something with the operator "&" and "*" etc. Because this code does not work for the moment...
Any help?
Thanks a lot.
EDIT:
Ok so the purpose of this code is to get a TextureInfos object at the end of the process. For this, I need to call the getTextureInfos method from TextureManager which also call getTextureInfos from TextureSet.
Here is the complete code for TextureManager.cpp
#include "TextureManager.h"
#include <iostream>
#include <fstream>
TextureManager TextureManager::m_TextureManager;
const std::string basePath="Assets/Graphics";
#pragma region Constructor
TextureManager::TextureManager()
{
textureSets.clear();
}
TextureManager::~TextureManager()
{
}
#pragma endregion
#pragma region Textures management
// Charge un set de texture a partir d'un nom de fichier
void TextureManager::LoadTextureset(std::string fileName,std::string key) {
TextureSet textureSet;
textureSet.init(basePath + fileName, key);
textureSets[key] = textureSet;
}
// Récupère une texture de la liste
TextureInfos TextureManager::getTextureInfos(std::string key, int id)
{
TextureSet textureSet = textureSets[key];
return textureSet.getTextureInfos(id); // HERE I GET AN ERROR
}
#pragma endregion
The line which is commented at the end is where i got an error:
no suitable user-defined conversion from "TextureInfos" to "TextureInfos" exists.
And for TextureSet.cpp:
#include "TextureSet.h"
#include <iostream>
#include <fstream>
#include "RapidXML\rapidxml.hpp"
#include "Debug.h"
const std::string basePath="Assets/Graphics";
using namespace rapidxml;
#pragma region Constructor
TextureSet::TextureSet()
{
}
TextureSet::~TextureSet()
{
}
#pragma endregion
void TextureSet::init(std::string l_filePath,std::string l_key)
{
filePath = l_filePath;
key = l_key;
// On détermine les URLs des fichiers
std::string setDescriptorPath = filePath + ".xml";
std::string setTilesetPath = filePath + ".png";
// On charge la texture
if (!textureSet.loadFromFile(setTilesetPath))
throw "ça load pas";
// On lis le xml
std::ifstream xmlDescriptor(setDescriptorPath);
if(!xmlDescriptor)
throw "Could not load tileset: " + setDescriptorPath;
std::string xmlDescriptorContents;
{
std::string line;
while(std::getline(xmlDescriptor, line))
xmlDescriptorContents += line;
}
std::vector<char> xmlData = std::vector<char>(xmlDescriptorContents.begin(), xmlDescriptorContents.end());
xmlData.push_back('\0');
//Create a parsed document with &xmlData[0] which is the char*
xml_document<> doc;
doc.parse<parse_no_data_nodes>(&xmlData[0]);
//Get the root node
xml_node<>* root = doc.first_node();
xml_node<>* imagefile = root->first_node("params");
maxRow = atoi(imagefile->first_attribute("maxRow")->value());
maxCol = atoi(imagefile->first_attribute("maxCol")->value());
tileWidth = atoi(imagefile->first_attribute("tileWidth")->value());
tileHeight = atoi(imagefile->first_attribute("tileHeight")->value());
tileCount = atoi(imagefile->first_attribute("tileCount")->value());
}
TextureInfos TextureSet::getTextureInfos(int id)
{
sf::Texture texture;
sf::IntRect rect;
if (id < tileCount) {
int x = (id % maxCol) * tileWidth;
int y = (id / maxCol) * tileHeight;
rect.left = x;
rect.top = y;
rect.width = tileWidth;
rect.height = tileHeight;
}
TextureInfos textureInfos(texture,rect);
return textureInfos;
}
TextureInfos.h
#include <unordered_map>
#include <vector>
#include <SFML\Graphics.hpp>
#include <string>
class TextureInfos
{
private:
protected:
public:
TextureInfos(sf::Texture& l_texture, sf::IntRect l_textureRect);
~TextureInfos();
sf::Texture& texture;
sf::IntRect textureRect;
};
No it doesn't work because it doesn't even compile. The reason it doesn't compile is because you try to return a pointer as a reference. A pointer and a reference are two different things.
For a quick, simple and dirty fix, change the return types from from TextureInfos& to TextureInfos*.
The quick fix outlined above is "dirty" because as you are using the code you will have a memory leak (you allocate memory with new but don't free it).
That can be solved two ways: Either return by value instead of using pointers/references. Or use smart pointers such as std::unique_ptr.
If you can avoid the use of dynamic memory allocation just edit your TextureSet::getTextureInfos to return a new stack object by value (notice that there will be a Return Value Optimization if you are worried about efficiency):
TextureInfos TextureSet::getTextureInfos(int id)
{
// ...
return TextureInfos(texture, rect);
}
Otherwise, if you really need dynamic allocation, use an std::shared_ptr to avoid memory leaks:
std::shared_ptr<TextureInfos> TextureSet::getTextureInfos(int id)
{
// ...
return std::make_shared<TextureInfos>(texture, rect);
}
According to your object naming I am assuming that you want to have a set of objects in your TextureSet. I would therefore suggest to add a private variable to your Object, and test new get requests against this object. You can then safely return a reference to a member.
One think that looks very worrying is that TextureInfos holds a reference to a texture, and you construct one from a passed reference.
TextureInfos(sf::Texture& l_texture, sf::IntRect l_textureRect);
sf::Texture& texture;
sf::IntRect textureRect;
Assuming the constructor does something like this
TextureInfos(sf::Texture& l_texture, sf::IntRect l_textureRect) :
texture(l_texture),
textureRect(l_textureRect)
{
}
... then you are entering a world of much pain. Look at GetTextureInfos() to see why:-
TextureInfos& TextureSet::getTextureInfos(int id)
{
sf::Texture texture;
sf::IntRect rect;
...
TextureInfos *textureInfos = new TextureInfos(texture,rect);
return textureInfos;
}
Ignoring the obvious issue that this will likely leak the returned object, you have the major problem that the returned object holds a reference to texture - but texture has gone out of scope so is no longer valid!
I can't propose a simple solution - but you need to make sure that you understand the lifetime management and ownership issues of the objects you're creating. Smart pointers (and returning entire objects rather than references) are usually key parts of this.

Why do I get an EXC_BAD_ACCESS when reading back a private class variable?

I have a Rectangle class shown below:
Header:
class Rectangle: public Polygon {
private:
float _width, _height;
public:
Rectangle(float width, float height);
float getWidth(float* width) const;
float getHeight(float* height) const;
bool isCollidingWith(Rectangle* other) const;
};
Selected Implementation:
Rectangle::Rectangle(float width, float height) : Polygon(explodeRect(width, height, new struct vertex[4]), 4) {
printf("creating rect %f x %f\n", width, height);
_width = width;
_height = height;
printf("set _width to %f\n", _width);
}
float Rectangle::getWidth(float* width) const {
printf("_w: %f\n", _width);
*width = _width;
return *width;
//return (*width = _width);
}
float Rectangle::getHeight(float* height) const {
return (*height = _height);
}
I initialize an instance of the Rectangle class, and the output indicates that the _width variable is being correctly assigned. However, when I later try to read the variable using the getWidth method, I get an EXC_BAD_ACCESS error on the line:
printf("_w: %f\n", _width);
Why can I no longer read this variable? I get the same problem with the _height variable as well.
EDIT: I would also like to note that if I skip reading the width, I get an error trying to read public variables directly from the object, e.g. when I try to read its x position with obj->x.
EDIT 2: Could this be from the fact that the object is an instance of a subclass of Rectangle, and this subclass is defined in a different file than Rectangle is? I am also reading the values from a third file.
EDIT 3: More code below.
I am trying to re-create Tetris with OpenGL. In my display method, I have this code to draw the rectangles:
if(fallingBlock != nullptr) {
printf("drawing falling block at (%f, %f)\n", fallingBlock->x, fallingBlock->y);
draw(fallingBlock);
}
fallingBlock is defined as a global variable at the top of my file:
Block* fallingBlock;
From my main, I call an initVars method that subsequently calls a startDroppingBlock method. Here it is:
void startDroppingBlock() {
Block* block = availableBlocks[random() % numAvailableBlocks].copy();
block->x = 0.5;
block->y = SCREEN_TOP;
block->dy = -0.01f;
//printf("copied block is at (%f, %f)\n", block->x, block->y);
fallingBlock = block;
}
And here is my block drawing method:
void draw(Block* obj) {
bool shape[3][3];
obj->getShape(shape);
//printf("got shape: {%d, %d, %d}, {%d, %d, %d}, {%d, %d, %d}\n", shape[0][0], shape[0][1], shape[0][2], shape[1][0], shape[1][1], shape[1][2], shape[2][0], shape[2][1], shape[2][2]);
/*float pieceWidth;
obj->getWidth(&pieceWidth);
pieceWidth /= 3.0f;*/
float pieceWidth = obj->getWidth();
for(unsigned int i=0; i<3; i++) {
for(unsigned int j=0; j<3; j++) {
if(shape[i][j]) {
Square rect = Square(pieceWidth);
rect.x = obj->x + pieceWidth * j;
rect.y = obj->y + pieceWidth * i;
rect.color = obj->color;
draw(&rect);
}
}
}
}
I get an EXC_BAD_ACCESS error on the line [...]. Why can I no longer read this variable? I get the same problem with the _height variable as well. [later...] I have tried both float pieceWidth; obj->getWidth(&pieceWidth); and obj->getWidth(new float) - the actual error is on the line where I read _width, before I even use the passed in pointer. [later...] I modified the getWidth and getHeight methods to just simply return _width and _height. Now I just get an error on return _width;
In this case I see you are using a Rectangle* pointer as obj->getWidth which can as well lead to a bad access error if obj is not a valid pointer.
It is to note that I don't quite understand your getter method at all. A simplified (and possibly standard) version of it might be:
float Rectangle::getWidth() const {
return _width;
}
With the only difference that when you used:
// float a;
// float b;
a = rect.getWidth(&b);
you can now do:
// float a;
// float b;
a = b = rect.getWidth();
which is possibly cleaner and will surely don't cause such an error. A good rule of thumb is never to use pointers when possible. If you need to modify a variable inside a function just use a reference.

Call constructor from other method in C++

I am not sure is that legal or not in C++:
class Image
{
Image(int w, int h) // constructor
{
...
}
Image GetSpecialImage()
{
Image rVal(10,10);
return rVal;
}
}
Do I need to use another middle level init() method to do this in C++? If yes, can you please show me how?
EDIT: Eventhough you say it's fine, it does not really do what I want to do... Let me give you some more code:
class Image
{
float* data;
int w;
int h;
Image(int w, int h) // constructor
{
this->w = w;
this->h = h;
data = (float*) malloc ( w * h * sizeof(float) );
}
Image GetSpecialImage()
{
Image rVal(this->w,this->h);
for(i=0;i<this->w * this->h;i++)
{
rVal.data[i] = this->data[i] + 1;
}
return rVal;
}
}
int main()
{
Image temp(100, 100);
Image result = temp.GetSpecialImage();
cout<<result.data[0];
return 0;
}
Is there anything wrong with this part?
As Seth said, that is legal.
Something you could change to make it work even better is to make GetSpecialImage a static function. A static function defined in a class is a class function instead of an object function. That means you don't need an object in order to call it.
It would then be called like this: Image special = Image::GetSpecialImage();
Yes, you can do this. I would just do this though
Image GetSpecialImage()
{
return Image(10,10);
}
While there's nothing wrong with this code (well, except for returning a local, which is a no-no), I guess what you're looking for is a static constructor pattern. Like so:
class Image{
public:
static Image* GetSpecialImage(){
return new Image(10,10);
}
};
//and call it so
Image *i = Image::GetSpecialImage();

Using inheritance to pass a non-static variable between classes

I'm researching UI's as a portfolio project and I ran into a little bit of trouble when it comes to inheritance. The problem I'm facing is this: I have two classes, R_GUI, in which I draw the form, and Button, where I draw the buttons. I want the Buttons to be positioned inside the FORM. I store the FORM position as form_x, and form_y. Here are my two classes:
class R_GUI
{
private:
bool get_pos_only_once;
bool move_form;
public:
int form_x, form_y;
int form_height, form_width;
int handle_bar_y;
inline void Form(int pos_x, int pos_y, int height, int width);
//inline void Button(int id, string ButtonText, int pos_x, int pos_y);
inline void Update_form(void);
inline void UPDATE(void);
inline ~R_GUI( );
inline R_GUI( )
{
d3dInit();
get_pos_only_once = false;
move_form = false;
form_x = 0;
form_y = 0;
handle_bar_y = 40;
}
};
and the Button class:
class Button: public R_GUI
{
private:
int b_form_x, b_form_y;
int b_handle_y;
int button_width, button_height;
public:
inline void Draw(string ButtonText, int b_pos_x, int b_pos_y);
Button()
{
b_form_x = R_GUI::form_x;
b_form_y = R_GUI::form_y;
b_handle_y = 20;
button_width = 90;
button_height = 35;
}
~Button();
};
As you can see, I'm trying to give b_form_x the value of form_x (which is a variable from R_GUI). form_x has a value, given in Form( );:
inline void R_GUI::Form(int pos_x, int pos_y, int height, int width)
{
if(get_pos_only_once == false)
{
form_x = pos_x;
form_y = pos_y;
form_height = height;
form_width = width;
get_pos_only_once = true;
}
//Create the form outline
d3dLine(pos_x,pos_y,pos_x+width,pos_y,dbRGB(50,50,50));
d3dLine(pos_x,pos_y,pos_x,pos_y+height,dbRGB(50,50,50));
d3dLine(pos_x+width,pos_y,pos_x+width,pos_y+height,dbRGB(50,50,50));
d3dLine(pos_x,pos_y+height,pos_x+width,pos_y+height,dbRGB(50,50,50));
//Create the handle bar
d3dLine(pos_x,pos_y+handle_bar_y,pos_x+width,pos_y+handle_bar_y,dbRGB(50,50,50));
//Fill the Handlebar;
d3dBox(pos_x,pos_y,pos_x+width,pos_y+handle_bar_y,dbRGB(3,3,3),dbRGB(3,3,3),dbRGB(3,3,3),dbRGB(3,3,3));
}
Yet, when I update the Form's Position, R_GUI::form_x value doesn't change. Any idea what I am doing wrong?
You don't want to have a second variable in your subclass (b_form_x). Eliminate it entirely. Instead, you want to use this->form_x, which in the Button will be inherited from R_GUI. The same applies for b_form_y.
this refers to the current instance of an object, and contains not only your local member variables but also any member variables inherited from classes all the way up the hierarchy as well.