1
class BaseObj
{
public:
    int position;
};

class EnemyObj: public BaseObj
{
public:
    int quantity;
};

class PlayerObj: public BaseObj
{
public:
    int lives;
};

int main()
{
    BaseObj* myObjs[3];

    BaseObj* b = new BaseObj();
    b->position = 1;
    myObjs[0] = b;

    EnemyObj* e = new EnemyObj();
    e->position = 2;
    e->quantity = 5;
    myObjs[1] = e;

    PlayerObj* p = new PlayerObj();
    p->position = 3;
    p->lives = 2;
    myObjs[2] = p;

    myObjs[2]->lives = 2;  // error is here
    return 0;
}

私の問題は、すべてのゲームオブジェクトの配列を作成して、それらをすべてまとめることができるようにすることですが、myObjs [2]-> livesにアクセスしようとすると、アクセスできません。これは私が得るエラーです:

error C2039: 'lives' : is not a member of 'BaseObj'
4

5 に答える 5

3

C ++は静的に型付けされた言語であり、これはすべての変数が特定の型を持っていることを意味します。配列にはへBaseObjのポインタが含まれています。これは、コンパイラがそのクラスで定義されたメンバーへのアクセスのみを許可することを意味します。

これらのポインタの1つが、より具体的な(つまり派生した)クラスインスタンスを指していることをコンパイラに次の2つの方法で伝えることができます。

  1. dynamic_cast<PlayerObj*>(p)

    PlayerObjこの式は、実際pにそのクラスのインスタンス(またはから派生したクラスのインスタンス)を指している場合は、へのポインターを返しますPlayerObj。そうでない場合は、nullでなくても、返されるポインタはnullポインタになりpます。

    dynamic_cast基本- >派生変換に使用できるようにするには、実行時型情報(RTTI)がコンパイラでデフォルトで有効になっていない場合に有効になっていること、および基本クラスが「ポリモーフィック型」であることを確認する必要があります。少なくとも1つの仮想メソッドが必要です。

  2. static_cast<PlayerObj*>(p)

    これは同じ変換を行いますが、から派生したクラスpのインスタンスまたはのインスタンスを指していない場合は、配列から書き出すときやオブジェクトを使用した後とまったく同じように、「未定義動作」の土地に入ります。それ。これは、プログラムのクラッシュ、クレイジーな動作、デーモンが鼻から飛び出す、またはさらに悪いことを意味する場合があります(たとえば、すべてがとにかく機能しているように見え、クラッシュは100万回実行された命令の後で発生します)。PlayerObjPlayerObjdelete

多くのC++プログラムで使用される解決策は、使用することだけですstatic_castが、最終的には、基本クラスに「型」データメンバー(列挙型など)を含めることによって、ポイントされたインスタンスの型を最初にチェックします。これは、コンパイラが提供するRTTIを使用するのではなく、基本的に独自のRTTIを構築していることを意味します。

于 2011-02-05T08:19:24.637 に答える
2

dynamic_castあなたの友だちです:

#include <iostream>
#include <memory>

class BaseObj {
public:
    BaseObj() : position(-1) {
    }

    virtual ~BaseObj() {
    }

    int position;
};

class EnemyObj : public BaseObj {
public:
    EnemyObj() : quantity(0) {
    }

    virtual ~EnemyObj() {
    }

    int quantity;
};

class PlayerObj : public BaseObj {
public:
    PlayerObj() : lives(9) {
    }

    virtual ~PlayerObj() {
    }

    int lives;
};

int main() {
    BaseObj* myObjs[3];

    BaseObj* b = new BaseObj();

    b->position = 1;
    myObjs[0] = b;

    EnemyObj* e = new EnemyObj();
    e->position = 2;
    e->quantity = 5;
    myObjs[1] = e;

    PlayerObj* p = new PlayerObj();
    p->position = 3;
    p->lives = 2;
    myObjs[2] = p;

    if (PlayerObj * const player = dynamic_cast<PlayerObj*>(myObjs[0])) {
        std::cout << player << "\n";
        player->lives = 2;
    }
    if (PlayerObj * const player = dynamic_cast<PlayerObj*>(myObjs[1])) {
        std::cout << player << "\n";
        player->lives = 2;
    }
    if (PlayerObj * const player = dynamic_cast<PlayerObj*>(myObjs[2])) {
        std::cout << player << "\n";
        player->lives = 2;
    }

    return 0;
}
于 2011-02-05T08:15:29.950 に答える
1

あなたはこのようにすることができます:

PlayerObj* player = dynamic_cast<PlayerObj*>(myObjs[2]);
if(player)
{
    player->lives = ...
}

または、myObjs[2]のタイプがPlayerObj*であることが確実な場合は、次を使用できます。

(static_cast<PlayerObj*>(myObjs[2]))->lives = ...
于 2011-02-05T07:58:08.127 に答える
1

迅速な返信ありがとうございます。戻って、問題の修正に協力してくれたことを皆さんに知らせてください。今ではすべてが完全に機能しています。

私は一緒に行きました

if(myObjs[2].type == PlayerObj)
{
      (static_cast <PlayerObj*>(myObjs[2]))->lives = 0;
}

そして、オブジェクト型列挙型を基本クラスに追加して、型を定義しました。

于 2011-02-05T09:07:14.800 に答える