C++双指针成员访问

4

C++(Arduino封装器)问题:我正在Arduino上编写一个射击游戏,它连接了一个LCD -

我有一个基类(Sprite),从这个类派生出其他类- AlienMissilePlayer。 Alien类的构造函数还具有私有成员pMissile(指向Missile类的指针)-“对象中的对象”应该是一种描述方式。 [当一个Alien发射导弹时,它将自己的(x,y)坐标传递给导弹,导弹具有从Alien的坐标开始移动的方法]

我的问题是:如何通过Alien对象访问导弹的坐标? 简化后的代码如下,我还绘制了一个表示类的图:

// Bass class - has a form/shape, x and y position  
class Sprite
{
  public:
    Sprite(unsigned char * const spacePtrIn, unsigned int xInit, unsigned int yInit);
    virtual void Move() = 0;
    void Render() { display.drawBitmap(x,y, spacePtr, 5, 6, BLACK); }
    unsigned int getX()    const { return x; } 
    unsigned int getY()    const { return y; }
  protected:
    unsigned char *spacePtr;
    unsigned int x, y;
};


// Derived class "Missile", also a sprite and has a specific form/shape, and specific (x,y) derived from input sprite
class Missile : public Sprite
{
public:
   Missile(): Sprite(&spaceMissile[0], 0, 0) {}
   virtual void Move();  // its own method of moving
};

// Derived class "Alien" - has a specific form/shape, and specific (x,y) position
class Alien : public Sprite
{
public:
   Alien(); 
   virtual void Move();   // its own method of moving
private:
   Missile *pMissile;
};

Alien::Alien(): Sprite(&spaceAlien[0], random(5, 75), random(4, 10))
{
  Missile MissileArray[MaxAmmoSize];
  pMissile = &MissileArray[0];
}


void Alien::Move()
{ 
  if( random(10) % 2 == 0 )
    x += 1;
  if( random(10) % 3 == 0 )
    y += 1;

  if( (pMissile != NULL) && (random(10) == 1) )
  {
    pMissile->setCoord(x, y);
    pMissile->Move();  // move the missile   
    pMissile++;        // move onto the next missile in the array
  }
  Render();
}

/*****************************************************************************************/
Alien MONSTER;
Player HERO;
Alien *pMONSTER = &MONSTER;

void loop()
{
  display.clearDisplay();
  MONSTER.Move();
  HERO.Move(); 
  pMONSTER->getX(); // this is x location of MONSTER
  **// how does pMONSTER access pMissile(x,y) within MONSTER.** 
  delay(100);
  display.display();
}

图片描述

嵌入式C++类交互问题


简短的回答是“它不行”。你需要在Alien中提供一个接口,让你获取pMissile的副本,或者提供一个转发请求的接口。或者,将pMissile从Alien中移除,并将其视为其他实体的平等对象。 - Joe Z
一个小提示:将Alien等子类作为Sprite的子类并不是很好的设计。Alien等拥有与它们相关联的Sprite(也许有几个),但它们是游戏对象。使用组合可能比继承更好。这样做也许更容易弄清楚如何实现你所要求的功能。 - hyde
2个回答

1
常见的方法是在Alien中添加一个getter函数:
class Alien {
public:
    Missile* getMissile() { return pMissile; }
}

使用它:

Alien* a = getAlienFromSomewhere();
auto pMissile = a.GetMissile();
if (pMissile != NULL) {
    x = pMissile->getX();
    y = pMissile->getY();
}

0

我想你想通过外星人来访问你的导弹位置,以测试与你的英雄实体的碰撞,但如果你需要跟踪你的导弹,你不应该像在Alien::Move()中所示那样用指针“走”到下一个导弹。这样做会丢失数组开头的引用。

在我看来,我会在你的外星人类中做这样的事情:

// Bass class - has a form/shape, x and y position  
class Sprite
{
  public:
    Sprite(unsigned char * const spacePtrIn, unsigned int xInit, unsigned int yInit);
    virtual void Move() = 0;
    void Render() { display.drawBitmap(x,y, spacePtr, 5, 6, BLACK); }
    unsigned int& getX()    const { return x; } 
    unsigned int& getY()    const { return y; }
  protected:
    unsigned char *spacePtr;
    unsigned int x, y;
};


// Derived class "Missile", also a sprite and has a specific form/shape, and specific (x,y) derived from input sprite
class Missile : public Sprite
{
public:
   Missile(): Sprite(&spaceMissile[0], 0, 0) {}
   virtual void Move();  // its own method of moving
};

// Derived class "Alien" - has a specific form/shape, and specific (x,y) position
class Alien : public Sprite
{
public:
   Alien(); 
   ~Alien(); // a destructor to cleanup your missiles - arduino have almost no memory to handle leaks ;-) 
   virtual void Move();   // its own method of moving

   inline Missile& getMissile(unsigned char n) { return pMissile[n];          }
   inline Missile& operator[](unsigned char n) { return getMissile(n);        }
   inline unsigned int& getX(unsigned char n)  { return getMissile(n).getX(); }
   inline unsigned int& getY(unsigned char n)  { return getMissile(n).getY(); }

private:
   Missile *pMissile;
   // adding the code to handle the count
   unsigned char missileCount;
};

Alien::Alien(): 
  Sprite(&spaceAlien[0], random(5, 75), random(4, 10)),
  missileCount(0)
{
  // this way of allocation creates a local object that is destroyed by the end of this scope
  //Missile MissileArray[MaxAmmoSize];
  //pMissile = &MissileArray[0];

  // so you should do somethin like this
  pMissile = new Missile[MaxAmmoSize];
}

Alien()::~Alien()
{
  delete[] pMissile;
}

void Alien::Move()
{ 
  if( random(10) % 2 == 0 )
    x += 1;
  if( random(10) % 3 == 0 )
    y += 1;

  if( (pMissile != NULL) && (random(10) == 1) )
  {
    // my proposal to fire it up
    Missile& missile = pMissile[missileCount];
    missile->setCoord(x, y);
    missile->Move();  // move the missile   
    missileCount++;   // move onto the next missile in the array
  }
  Render();
}

使用这样的代码,您可以通过以下方式访问导弹的位置:
MONSTER.getX(0) += 1;
MONSTER[0].getY() +=1;
MONSTER.getMissile(1).getX() = 10;

为了更清晰,我建议将getX()getY()方法重构为x()y(),因为它们返回到类内容的引用(这样做,您还应该将xy成员更名为其他名称,否则你会因命名冲突而变得疯狂)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接