1

私はC++が初めてで、これに問題があります。そのため、ジェネリック サブクラスを使用して、互いのフィールドを呼び出すことができるクラスを作成しようとしています。

基本的には、ジェネリック型と、お互いに強み/弱みを持つ 3 つの型が存在するゲームを作ろうとしています。私は実際に Java の経験しかありません。この種のことを C++ に変換するのは、私には合いません。

ジェネリック型は、タイプ 1、タイプ 2、タイプ 3 の 3 つのタイプに分けられます。

ジェネリック型は具体的である必要があります

ジェネリック型には、攻撃、防御、ヒットポイントのフィールドがあります

タイプ 1、2、および 3 はすべてこれらのフィールドを継承します。

ジェネリック クラスで仮想関数を作成しようとしています。

virtual void attack(Generic* g);

問題は、たとえば作成しようとするとtype_1.attack(generic)、ジェネリックのヒットポイントを取得するために g->hitpoints を実行したいのですが、C++ ではそのように機能しないようです。

さらに、型 1、2、および 3 にはすべてジェネリック型のヘッダーが含まれているため、何か間違ったことをしているに違いないことはわかっていますが、これら 3 つのヘッダーを main.cpp に含めたい場合は、ジェネリック 3 を宣言するとエラーが発生します。別の時間。

どうすればこれを行うことができますか?

申し訳ありませんが、これは非常に具体的な質問であり、少しあいまいです。何か明確にする必要がある場合はお知らせください

編集:これが私が話していることの基本的なセットアップです

//in generic.h

class Generic {
protected:
    int hitpoints;
    int strength;
    int defense;
public:
    virtual void attack(Generic* g);
};

//type1.h
#include 'generic.h'
class Type1 : public Generic {
    void attack (Generic* g);
};

//in type1.cpp
void Type1::attack(Generic*g) {
    g->hitpoints = strength - g->defense;
}

4

5 に答える 5

1

2 番目の問題 (複数回定義されたクラス) を回避するために、インクルード ガードと呼ばれるものがあります (同じファイルを複数回インクルードしないように保護します)。次のように機能します。

// File: type1.h
// At the very beginning
#ifndef type1_h
#define type1_h

// Here come the rest of your file and, at the end:

#endif

このように、ファイルの内容は一度だけ含まれます。その後type1_hは定義されるため、すべてがスキップされます。#defineこれは、C++ で広く受け入れられているの唯一の使用方法かもしれません。

最初の問題に関してprotectedは、派生クラスがそのメンバーまたは自分のクラスのオブジェクトを読み取ることができることを意味しますが、それ以外は誰も読み取れません。これには、派生クラスが、基本クラス自体を含む別のクラスに属するオブジェクトのそのメンバーを読み取れないことが含まれます。残念ながら、デザインを再考する必要があります。

あなたができる最善のことは、メンバーのプライバシーを変更することprotectedです. データ メンバーがクラスで良い考えになることはめったにありません (構造体は別のものです)。publicprivatepublic

class Generic {
private:
    int hitpoints;
    int strength;
    int defense;
public:
    virtual void attack(Generic* g);

    void SetHitpoints(int hp) {hitpoints = hp;}
    int GetDefense() {return defense;}
};
于 2013-10-12T18:05:53.870 に答える
1

タイプ 1、2、および 3 にはすべてジェネリック タイプのヘッダーが含まれていますが、これら 3 つのヘッダーを main.cpp に含めたい場合、ジェネリック 3 を別々に宣言するとエラーが発生します。

クラスが 1 回だけ宣言されていることを確認する必要があります。これは通常、.h ファイルのガードで行われます。

//generic.h
#ifndef GENERIC_H
#define GENERIC_H

//all declarations go here

#endif /* GENERIC_H */

と入力する#include "generic.h"と、C++ プロセッサは基本的に foo.h の内容を貼り付けるだけです。(それぞれが generic.h をインクルードするクラス Type1、Type2、および Type3 のインクルードを介して) 3 回インクルードしたため、クラスは 3 回宣言されます。

于 2013-10-12T18:07:19.607 に答える
1

次のようにする必要があります。

// generic.h
#pragma once

class Generic {
  protected:
    int hitpoints_;
    int strength_;
    int defense_;

    void do_damage(Generic* g, int damage) { g->hitpoints_ -= damage; }
  public:
    virtual void attack(Generic* g) = 0;

    int hitpoints() const { return hitpoints_; }
    int strength() const { return strength_; }
    int defense() const { return defense_; }
 };

 // type1.cpp
 void Type1::attack(Generic* g) {
   do_damage(g, strength_ - g->defense());
 }
于 2013-10-12T18:15:19.307 に答える
1

for data membersの意味はprotected、予想とは微妙に異なります。A保護されたデータ メンバーを持つdクラスと、 (パブリック継承を使用して)Bから継承するクラスがある場合、のメンバー関数はアクセスできますが、タイプ のオブジェクトにのみアクセスでき、タイプ のオブジェクトにはアクセスできません。それが紛らわしいと思われる場合は、コード例でより明確になることを願っています:ABdBA

class A {
protected:
    int d;
};

class B : public A {
    void fine(B& b)  { b.d = 0; }
    void wrong(A& a) { a.d = 0; }
};

int main() { }

名前が示すように、関数内の代入は問題ありませんが、コードをコンパイルしようとすると、内の代入fineに対してコンパイラ エラーが発生します。wrongこれに対処する最善の方法は、おそらくデータ メンバーを非公開にし、abys.7 の回答のように、データ メンバーを操作する保護されたメンバー関数を書き込むことです。

二重包含の問題については、include Guardsまたは#pragma onceのいずれかを使用します。

于 2013-10-12T19:27:46.010 に答える