6

カスタムクラスのStudentオブジェクトの配列があります。CourseStudentとResearchStudentはどちらもStudentを継承しており、Studentのすべてのインスタンスはこれらのいずれかです。

配列を調べて、各Studentのサブタイプを判別し、それらに対してサブタイプ固有のメンバー関数を呼び出す関数があります。

問題は、これらの関数がオーバーロードされていないため、Studentで見つからないため、コンパイラーが大騒ぎすることです。

Studentへのポインターがある場合、そのStudentのサブタイプへのポインターを取得する方法はありますか?コンパイル時のエラーを回避するために、ここで何らかの偽のキャストを作成する必要がありますか?

4

5 に答える 5

11

最良の方法は、仮想関数を使用することです。

class Student
{
   // ...
   virtual void SpecificFunction() = 0; /* = 0 means it's abstract; it must be implemented by a subclass */
   // ...
};

class CourseStudent
{
    void SpecificFunction() { ... }
};

次に、次のことができます。

Student *student;
student->SpecificFunction();

(より悪い)代替手段は以下を使用することができますdynamic_cast

Student *student;
CourseStudent *cs = dynamic_cast<CourseStudent *>(student);

if (cs) {
   /* student is a CourseStudent.. */
   cs->SpecificFunction();
}
于 2010-04-01T11:02:22.630 に答える
7

動的キャストが必要です。

Student * s = new ...;    // Create student of some sort.

if ( ResearchStudent * r = dynamic_cast<ReasearchStudent*>( s ) ) {
   r->ResFunc();
}
else if ( CourseStudent * c = dynamic_cast<CourseStudent*>( s ) ) {
   c->CourseFunc();
}
else {
   throw "Unknown student type.";
}

クラスに少なくとも1つの仮想関数がある場合、これはコンパイラによって維持される型情報を使用することに注意してください。他のすべてが失敗した場合は、デストラクタを仮想にします(この場合はとにかくそうする必要があります)。独自のタイプ情報を維持するために、常にこのアプローチを好む必要があります。

于 2010-04-01T11:03:24.673 に答える
3

サブクラスメンバー関数はそれらのサブクラスに固有であるため、ここでは仮想関数は不適切です(たとえば、CourseStudentにはユニットのリストがありますが、ResearchStudentにはないため、ResearchStudentでのgetUnits()関数の実装はまったく意味がありません)

動的キャストと静的キャスト(cplusplus.com型キャスト)について少し読んだことがありますが、この場合は静的キャストの方が適切だと思います。

static_castの一般的な欠点は、実行時にサブタイプにキャストされているオブジェクトが実際にはそのサブタイプであり、他のサブタイプではないことを確認するためのチェックを実行しないことです。この場合、型を実行する前に(サブクラスコンストラクターに設定され、ミューテーターを持たないプライベートデータメンバーを使用して)型を具体的にチェックしているので、チェックが良好である限り、静的キャストに問題はありません。 。動的キャストは型チェックを実行するためにより多くのランタイムリソースを必要とするため、静的キャストの方が効率的です。

メンバーが期待されるタイプではない可能性がある場合は、静的キャストは適切ではないため、動的キャストを使用します(これは割り当てであるため、送信後はコードを維持する必要がないため、誰かが後でそれを台無しにするリスクはありません)。

于 2010-04-01T11:27:52.717 に答える
2

これは、基本クラスで純粋仮想メンバー関数を使用し、実際の作業を行う派生クラスでオーバーライドする場合にほぼ確実に当てはまります。

于 2010-04-01T11:02:18.713 に答える
1

あなたはそれが必要static_castです。これらの関数は基本クラスの仮想メンバーではないため、基本クラスへのポインターポインターを介してそれらを呼び出すことはできません。オブジェクトの実際のタイプに明示的にキャストする必要があります。

この問題は通常、仮想関数を使用して解決するのが最適です。コードでオブジェクトタイプをチェックする必要がなくなり、コードが少なくなり、バグの表面が少なくなります。

于 2010-04-01T11:01:27.860 に答える