C++继承子类可修改变量

C++ inheritance subclass modifiable variables

本文关键字:修改 变量 子类 继承 C++      更新时间:2023-10-16

帮助我了解如何在子类中使用超类变量并能够对其进行更改,我正在使用SDL库制作一个克隆Space Invaders 2D游戏

首先,我有一个继承自SDL_Rect的Rectangle类,看起来像这样,我会把不重要的部分去掉

//Rectangle.h 
namespace galaxy{
struct Rectangle : public SDL_Rect{
    Rectangle();
    Rectangle(int xx, int yy, int hh, int ww);
    Rectangel centeredRect(int width, int height) const
    bool overlaps(const Rectangle& other) const;
    };
}

我将省略.cpp,因为很容易看出矩形天使在其中扮演的角色,我不想让你们厌烦,

然后我有一个精灵类,它是游戏中人物的超类,

namespace galaxy{
class Sprite{
public:
virtual void draw() = 0;
virtual ~Sprite();
virtual void keyLeft(SDLKey k);
virtual void keyRight(SDLKey k);
......more buttons
protected:
Sprite(int x, int y, int h, int w);
private:
Rectangle rect;
Sprite (const Sprite&);
const Sprite& operator=(const Sprite&);
};
}

在.cpp文件中,我有以下代码

namespace galaxy{
Sprite::Sprite{int x, int y, int h , int w) : rect (x, y, h, w){}
Sprite::~Sprite(){}
const Rectangel& Sprite::getRect() const{
return rect;
}
void Sprite::keyLeft(SDLKey k){}
void Sprite::keyRight(SDLKey k){}
void Sprite::keyDown(SDLKey k){}
...more buttons
}

然后到问题所在的地方,我有另一个类Ship,我想从超类重载keyLeft,矩形rect跟在坐标后面,我需要更改子类中的x和y,但在使用r.x++下面的构造时;表现为在函数内部,并且在退出函数时清除对矩形x的更改,在尝试访问Ship类中的rect时I get error not reachable,在通过r=getRect()获取rect时;更改为r只是在函数内部,但飞船不会在屏幕上移动。

//Ship.h
    namespace galaxy {
    class Ship : public Sprite{
    public:


        void keyLeft(SDLKey k);
        void keyRight(SDLKey k);
        void keyDown(SDLKey k);
        void keyUp(SDLKey k);
        void space(SDLKey k);
        Ship(int x, int y, int hits);
    private:
        SDL_Surface* ship;
        int hits;
    };
}
//Ship.cpp
using namespace std;

namespace galaxy{
Rectangel r;

    Ship::Ship(int x, int y, int hits) : Sprite(x, y, NULL, NULL), hits(hits){
        ship = IMG_Load("Ship.png");
    }

     //Here is where my problem is.....
        void Ship::keyLeft(SDLKey k){ 
            std::cout << "Im here!n";    
            std::cout << r.getX(); // outputs 250
            r.x--;
            std::cout << r.getX(); // outputs 251
        }
        void Ship::keyRight(SDLKey k){
        std::cout << "Im here!n";
        }
        void Ship::keyDown(SDLKey k){
        std::cout << "Im here!n";
        }
        void Ship::keyUp(SDLKey k){
        std::cout << "Im here!n";
        }
        void Ship::space(SDLKey k){
        std::cout << "Im here!n";
        }

    void Ship::draw(){
        r = getRect();
        SDL_BlitSurface(ship, NULL, sys.screen, &r);
    }
}

现在我这样做:

 #ifndef SHIP_H
#define SHIP_H
#include "Sprite.h"
#include <string>
namespace galaxy {
    class Ship : public Sprite{
    public:
        /*static Ship* getInstance(int x, int y, int hits);*/
        void draw();

        //virtual void perform() = 0;
        /*int getHits() const;*/
        int getX() const;
        int getY() const;
        const Rectangel& getRect() const;
        void keyLeft(SDLKey k);
        void keyRight(SDLKey k);
        void keyDown(SDLKey k);
        void keyUp(SDLKey k);
        void space(SDLKey k);
        //~Ship();
        //protected:
        Ship(int x, int y, int hits);
    private:
        SDL_Surface* ship;
        int hits;
        Rectangel rect;
    };
}
#endif

#include "Ship.h"
#include "Globals.h"
#include "Sprite.h"
#include <SDL_image.h>
#include <iostream>
using namespace std;

namespace galaxy{
Rectangel r;
    /*Ship* Ship::getInstance(int x, int y, int hits){
     return new Ship(x, y, hits);
     }*/
    Ship::Ship(int x, int y, int hits) : Sprite(x, y, NULL, NULL), hits(hits){
        ship = IMG_Load("Ship.png");
    }
        const Rectangel& Ship::getRect() const{ 
        return rect; 
    }
        void Ship::keyLeft(SDLKey k){ 
            std::cout << "Im here!n";    
            rect.x--;
        }
        void Ship::keyRight(SDLKey k){
        std::cout << "Im here!n";
        }
        void Ship::keyDown(SDLKey k){
        std::cout << "Im here!n";
        }
        void Ship::keyUp(SDLKey k){
        std::cout << "Im here!n";
        }
        void Ship::space(SDLKey k){
        std::cout << "Im here!n";
        }
   /* int Ship::getHits() const{ 
        return hits; 
    }*/
    int Ship::getX() const{ 
        return r.getX();
    }
    int Ship::getY() const{ 
        return r.getY();
    }
    void Ship::draw(){
        r = getRect();
        SDL_BlitSurface(ship, NULL, sys.screen, &r);
    }
}

但这只是一个变通办法,这样我就不会永远被困。

如果你这样做:

Rectangel r;
...
r = getRect();

然后,您只需将原始矩形复制到r变量中,当您更改它时,原始矩形不会更改。也许为了快速解决问题,您可以在Ship类中实现setRect函数,以便能够实际写回修改后的数据。

void Ship::setRect(const Rectangel& rr) { rect = rr; }

如果您想直接从Sprite基类访问rect,则需要为rect提供受保护的可见性,如下所示:

class Sprite
{
    [...]
protected:
    Rectangle rect;
    [...]
};