0

I have a class Rect such that it holds the width, height, x and y values of a shape. The class can draw using the values in the parameter and move the drawn rect.

     Rect::Rect(w, h, x, y, const std::string &image_path) : _w(w), _h(h), 
  _x(x), _y(y)
     {

     SDL_Surface *surface = IMG_Load(image_path.c_str());
     if (!surface) {
     std::cerr << "Failed to create surface.";

     }

    //create texture
    texture = SDL_CreateTextureFromSurface(Window::renderer, surface);
    if (!texture) {
    std::cerr << "Failed to create worker texture.";

     }

     SDL_FreeSurface(surface);

     }

     Rect::~Rect() 
     {
     SDL_DestroyTexture(texture);
     }

     Rect::draw()
     {
       //where the constructor parameters are parsed
       SDL_Rect rect= {_x, _y, _w, _h} ;

       //extra code about some SDL texture stuff and RenderCopy
     }

     Rect::moveX(int x){

     _x +=x;

     }

In my Unit class, I include the class Rect and I create my units, draw them in the same function. There is another function in unit that moves rect by checking another value from another class that changes.

  Unit::Unit()
  Unit::~Unit()

    void Unit::createUnit(int type, int x, int y){
      if (type == 0)
      {
      Rect unit1(unitImageWidth, unitImageSizeHeight, x, y, "res/unit1.png");

      }
      if (type == 1)
      {
      Rect unit2(unitImageWidth, unitImageSizeHeight, x, y, "res/unit2.png");

      }
    }

   void Unit::moveUnit(int x){
      if(selection == 0)
      {
      unit1.movex(x);
      }

      if (selection ==  1)
      {
      unit2.movex(x);
      }
    }

My question is:

When in Unit::moveUnit(), how can I reference the object Rect "unit1" and Rect "unit2" that are initialized in Unit::createUnit()?

When I try to compile, it say that unit1 and unit2 are undefined.

  • 2
    `unit1` and `unit2` are local variables. They don't exist outside of their containing `{` `}` blocks. – melpomene Dec 12 '18 at 01:05
  • 3
    Those be local variables. They are gone as soon as they are out of scope. You need to make variables with a broader scope, perhaps class member variables. – user4581301 Dec 12 '18 at 01:06

2 Answers2

1

You can't do what you want to do. Non-static local variables are bound to their scope. They are only visible inside and are destroyed when the program exits the area bounded by the {} braces.

The simplest solution is to go in a completely different direction. Add to Unit a private variable to contain the Rect for example,

Rect sprite;

Then replace

void createUnit(int type, int x, int y);

with a Unit constructor

Unit(int type, int x, int y);

And implement the constructor something like

Unit::Unit(int type, int x, int y): sprite(unitImageWidth, 
                                           unitImageSizeHeight, 
                                           x, 
                                           y, 
                                           type == 0? "res/unit1.png": "res/unit2.png")
{

}

The colon : starts a Member Initializer List and that crazy ?: Is a one line if statement called the Ternary or Conditional Operator

Note: I don't know what unitImageWidth and unitImageSizeHeight are or where they come from. Make sure you do and make sure they are accessible.

moveUnit becomes

void Unit::moveUnit(int x)
{
    sprite.movex(x);
}

because sprite knows what it is and what image has been loaded and can move the Rect to x (or whatever movex does).

To use you

Unit myUnit(0, 1024, 42);  // creates a unit of type 0 at coordinates 1024,42
myUnit.movex(88); // moves myUnit to 88,42 (I think)
user4581301
  • 33,082
  • 7
  • 33
  • 54
0

Just add two Rect members in your class Unit, then you can use it in different member functions.
Better using pointer, as below:

class Unit
{
 public:
    Unit::Unit()
        : uint1(NULL), uint2(NULL){};
    Unit::~Unit()
    {
        if (uint1 != NULL) {
            delete unit1;
            uint1 = NULL;
        }
        if (uint2 != NULL) {
            delete unit2;
            uint2 = NULL;
        }
    };

    void Unit::createUnit(int type, int x, int y)
    {
        if (type == 0) {
            unit1 = new Rect(unitImageWidth, unitImageSizeHeight, x, y, "res/unit1.png");
        }
        if (type == 1) {
            unit2 = new Rect(unitImageWidth, unitImageSizeHeight, x, y, "res/unit2.png");
        }
    }

    void Unit::moveUnit(int x)
    {
        if (selection == 0) {
            unit1->movex(x);
        }

        if (selection == 1) {
            unit2->movex(x);
        }
    }

 private:
    Rect *unit1;
    Rect *unit2;
};
yjjjnls
  • 62
  • 5
  • I will also try to implement this in other places that I use Rect. Thank you. – Seb St Johnston Dec 12 '18 at 23:17
  • @SebiStJohnston Familiarize yourself with and take advantage of [The Rule of Three](https://stackoverflow.com/questions/4172722/what-is-the-rule-of-three) when applying this approach. – user4581301 Dec 12 '18 at 23:21