不同范围内的 C++ 对象引用

Posted

技术标签:

【中文标题】不同范围内的 C++ 对象引用【英文标题】:C++ Object referencing in different scopes 【发布时间】:2018-12-12 01:01:02 【问题描述】:

我有一个 Rect 类,它保存形状的宽度、高度、x 和 y 值。该类可以使用参数中的值进行绘制并移动绘制的矩形。

     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;

     

在我的 Unit 类中,我包含 Rect 类并创建我的单位,在同一个函数中绘制它们。 unit 中还有另一个函数,它通过检查另一个类中发生变化的另一个值来移动 rect。

  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);
      
    

我的问题是:

Unit::moveUnit()中,如何引用Unit::createUnit()中初始化的对象Rect"unit1"和Rect"unit2" >?

当我尝试编译时,它说 unit1 和 unit2 未定义。

【问题讨论】:

unit1unit2 是局部变量。它们不存在于它们包含的 块之外。 那些是局部变量。一旦超出范围,它们就会消失。您需要创建范围更广的变量,可能是类成员变量。 【参考方案1】:

你不能做你想做的事。非static 局部变量绑定到它们的scope。它们仅在内部可见,并在程序退出由 大括号包围的区域时被销毁。

最简单的解决方案是走向完全不同的方向。添加到Unit 一个private 变量以包含Rect,例如,

Rect sprite;

然后替换

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

使用Unit 构造函数

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

并实现类似的构造函数

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



冒号: 以Member Initializer List 开头,而疯狂的?: 是一个名为Ternary or Conditional Operator 的单行if 语句

注意:我不知道unitImageWidthunitImageSizeHeight 是什么,也不知道它们来自哪里。确保你这样做并确保它们是可访问的。

moveUnit变成了

void Unit::moveUnit(int x)

    sprite.movex(x);

因为sprite 知道它是什么以及加载了什么图像,并且可以将Rect 移动到x(或movex 所做的任何事情)。

使用你

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)

【讨论】:

谢谢。我会尝试实现它。【参考方案2】:

只需在你的 Unit 类中添加两个 Rect 成员,然后你就可以在不同的成员函数中使用它。 更好地使用指针,如下:

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;
;

【讨论】:

我也会尝试在我使用 Rect 的其他地方实现这一点。谢谢。 @SebiStJohnston 在应用此方法时熟悉并利用The Rule of Three。

以上是关于不同范围内的 C++ 对象引用的主要内容,如果未能解决你的问题,请参考以下文章

阐明在函数签名中将两个对不同范围的引用对象的引用绑定到相同生命周期的含义

python中的“引用”和C++的引用

在 C++ 中通过引用/值传递

C++ - 返回指针或常量引用

C++引用

c++ - 如何使用make链接c ++中不同目录中的对象而不在makefile中引用它们?