2

(私は C++ にかなり慣れていないので、これが初歩的なミスであることを願っています)

コードに問題があり、いくつかの属性を必要とするクラス「Player」があり、抽象クラスを使用して属性を指定しようとしています。

//player.h

class Player : public IUpdate, public IPositionable, public IMoveable, public IDrawable
{
public:
    Player(void);
    SDL_Rect get_position();
    void move(Uint32 dTime);
    void update(Uint32 dTime);
    void show(SDL_Surface* destination);
    ~Player(void);
private:
    SDL_Surface texture;
    int x, y;
};

そして、純粋仮想関数を次のようにオーバーライドしています。

//Player.cpp
Player::Player(void)
{
}

SDL_Rect Player::get_position()
{
    SDL_Rect rect;
    rect.h = 0;
    return rect;
}

void Player::move(Uint32 dTime)
{

}

void Player::update(Uint32 dTime)
{
    move(dTime);
}

void Player::show(SDL_Surface* destination)
{
    apply_surface(x, y, &texture, destination, NULL);
}

Player::~Player(void)
{
}

ただし、コンパイルエラーが発生し続けます:C2259: 'Player' : cannot instantiate abstract class

私が見る限り、純粋な仮想関数をオーバーライドする必要があります。Google で検索したところ、Player は非抽象化されたはずですが、Player はまだ抽象化されているように見えます。

編集:純粋な仮想関数:

class IPositionable
{
public:
    virtual SDL_Rect get_position() = 0;
private:
    int posX, posY;
};

class IUpdate
{
public:
    virtual void update (Uint32 dTime) = 0;
};

class IMoveable
{
public:
    int velX, velY;
    virtual void move(Uint32 dTime) = 0;
};

class IDrawable
{
public:
    virtual void show() = 0;
private:
    SDL_Surface texture;
};

class IHitbox
{
    virtual void check_collsion() = 0;
};

class IAnimated
{
    virtual void next_frame() = 0;
    int state, frame;
    int rows, columns;
};
4

5 に答える 5

4

あなたの問題はここにあります:

class IDrawable
{
public:
    virtual void show() = 0;
};

void Player::show(SDL_Surface* destination)
{
    apply_surface(x, y, &texture, destination, NULL);
}

Player::show(SDL_Surface* destination)純粋仮想メソッドをオーバーライドしないことに注意してくださいIDrawable::show()
メソッドをオーバーライドするには、派生クラスでまったく同じ関数シグネチャを使用する必要があります(共変の戻り型のみが許可されます)
。現在あるのは、show()派生クラスで名前が付けられたメソッドで、Baseクラスで指定されたメソッドを非表示show()にします。オーバーライドしません。それ。クラスコンパイラのすべての純粋仮想関数の定義を提供しPlayerないので、それが抽象クラスであることが正しくわかります。

于 2012-09-15T12:22:43.113 に答える
1

ベースの 1 つの純粋仮想関数をオーバーライドする代わりに、次のように、微妙に異なるシグネチャを持つ関数を宣言および定義した可能性があります。

struct base {
    virtual void foo(double d) = 0;
};

struct derived: base {
    // does not override base::foo; possible subtle error
    void foo(int i);
}

コードを見直して再確認することをお勧めします。C++11 を使用している場合は、関数をマークしてoverrideそのようなエラーをキャッチできます。

于 2012-09-15T11:34:12.837 に答える
0

確かに、純粋な仮想関数のオーバーライドが欠落していることが原因です-おそらく微妙な署名の違いです。

(vc9) のように、どの関数がまだオーバーライドされていないかをコンパイラが教えてくれると思います。

C2259: 'Player' : cannot instantiate abstract class
due to following members:
'void IUpdate::update(void)' : is abstract
virtualclass.cpp(3) : see declaration of 'IUpdate::update'

コンパイラがこれを報告しなかった場合は、継承されたインターフェイスを 1 つずつ削除して確認できます。

于 2012-09-15T11:42:51.917 に答える
0

抽象クラスは抽象です。つまり、何かが定義されておらず、宣言されているだけです。

これらすべてのメソッドを定義する必要があります。これらのクラスの宣言がないため、不足しているメソッドについてアドバイスすることはできません。

于 2012-09-15T11:19:13.043 に答える
0

C++ では、具体的に記述されていない限り、関数は仮想ではありません。

virtual void move(Uint32 dTime);

純粋仮想関数は次のように定義されます。

virtual void move(Uint32 dTime) = 0;

継承元の「インターフェース」(これは多重継承であることに注意してください.. C++はクラスとインターフェースに違いはありません)には、実装していない純粋な仮想関数があるため、クラスが抽象化されます。

于 2012-09-15T11:20:21.717 に答える