8

精巧な型指定子を使用することを選択する特に正当な理由はありますか?たとえば、特定の状況では、従属またはタイプを明確にするために、templateまたはキーワードを使用する必要があります。typenametemplate

しかし、列挙などでこれが発生する例は考えられません。次のコード例を見てください。

enum Foo { A,  B };

void bar(Foo foo);
void baz(enum Foo foo);

なぜ私は(またはその逆に)baz()提供される構文を使用することを選択するのですか?bar()あいまいなケースはありますか?

4

5 に答える 5

8

名前が別の「種類」の名前で隠されている状況に対処していない限り、このような指定子を使用する理由はありません。たとえばFoo、列挙型宣言にちなんで名付けられた変数を宣言することは完全に合法です。非公式に言えば、オブジェクト名と型名は独立した「名前空間」に存在するからです(より正式な仕様については3.3 / 4を参照)。

enum Foo { A, B };

int Foo;

宣言後、int Foo宣言barは無効になりますが、より複雑なbaz宣言は引き続き有効です。

于 2012-06-05T18:16:03.247 に答える
3

ユーザー定義型を宣言するには、複雑な型指定子が必要です。1つのユースケースは、型を前方宣言することです。万が一enum、スコープに表示されているのと同じ名前の関数がある場合は、関数宣言で詳細な型指定子を使用する必要があります。

enum A { A_START = 0 };

void A(enum A a) {}

int main() {
   enum A a;
   A( a );
}
于 2012-06-05T18:16:12.123 に答える
1

精巧な型指定子を使用することを選択する1つの理由は、ヘッダーで構造体またはクラスを前方宣言することです。タイプを定義するヘッダーが与えられた

// a.h
struct foo {};

そのヘッダーを含めて、関数のプロトタイプを作成できます

#include "a.h"
void foo(foo * ) ;

または、手の込んだタイプを使用します。

void foo(struct foo * ) ;

または、精巧なタイプを使用して明示的に前方宣言します。

struct foo ;
void foo( foo * ) ;

最後の2つの方法のいずれかを使用すると、ヘッダーが徐々に完全に接続されたWebに縮退するのを防ぐことができます。この場合、単一のヘッダーを含めると、残りのすべてが引き込まれます(私はそれが悲しいことに真実であるソフトウェア製品に取り組んでおり、多くの後に世界を再構築する必要がありますあなたが想像できるような種類の変更は論理的に分離されます)。

C ++ 11では、現在C ++ 01コンパイラでは許可されていない、この種の列挙型の前方参照も許可されることを理解しています。

于 2012-12-19T02:06:04.790 に答える
0

発生する可能性のある例は、同じ名前の型要素と非型要素がある場合です。精巧な型指定子を使用することにより、型を明示的に要求できます。

struct foo {};
void foo(struct foo) {}
int main() {
   struct foo f;
   foo(f);
}

精巧な型指定子がない場合、fooinは型ではなく、をmain参照します。さて、私はそれを本番コードに含めたくありませんが、あなたはそれが重要な例を求めただけです。タイプと関数(または変数)が異なる名前空間で定義されていて、ルックアップによって非タイプが以前に見つかった場合も、同じことが起こります。上記に置き換えることができます。void foo(struct foo)struct foostructenum

于 2012-06-05T18:16:58.600 に答える
0

以下で説明する前方宣言は、ElaboratedTypeSpecifierの兆候の1つです。

C ++やObjective-Cなどの一部のオブジェクト指向言語では、クラスを前方宣言する必要がある場合があります。これは、クラスの名前が型であることを知る必要があるが、構造を知る必要がない状況で行われます。

C ++では、クラスと構造体は次のように前方宣言できます。

class MyClass; 

struct MyStruct; 

C ++では、そのクラスへのポインター型のみを使用する必要がある場合は、クラスを前方宣言できます(すべてのオブジェクトポインターは同じサイズであり、これがコンパイラーが気にするものであるため)。これは、クラス定義内で特に役立ちます。たとえば、クラスに別のクラスへのポインタ(または参照)であるメンバーが含まれている場合です。

前方宣言は、ヘッダーを含める回数を減らすことでコンパイル時間を短縮するのに役立つ不要な結合を回避するために使用されます。これには3つの利点があります。

  • によって開かれるファイルの数を減らす#include(したがって、オペレーティングシステムの呼び出しの数)
  • 前処理されたファイルの量を減らす(ヘッダーが含まれていないため)
  • 前方宣言されたクラスが変更されたときの再コンパイルの影響を減らします。

実際のクラス型を使用する必要がある場合、たとえば、型が直接(ポインタではない)そのクラスであるメンバーがある場合、またはそれを基本クラスとして使用する必要がある場合、クラスの前方宣言は十分ではありません。または、メソッドでクラスのメソッドを使用する必要がある場合。

これにより、関連するヘッダーファイルをヘッダーファイルにインクルードすることなく、タイプへのポインターを使用できます(代わりに、.cppファイルにのみ必要です)。

これは、依存関係を減らし、コンパイル時間を改善するのに役立ちます。

Unreal Engine特にコアクラスはとにかく含まれていることが多いため、必ずしも必要なわけではありません。ただし、ヘッダーファイルを明示的にインクルードしていない場合は、プレフィックスを使用することをお勧めします。これを行う場合、ヘッダーを含んでいたファイルがそれを含まないように変更されても、コードはコンパイルされます。

前方宣言は適切ですが、ETSは避ける必要があります。型を前方宣言する場合は、ファイルスコープで明示的に宣言するのが最善です。

悪い:

class Bad
 {
     void Func(class Y* YParam);
     class Z* ZProp;
 };
 

良い:

 class Y;
 class Z;
 class Good
 {
     void Func(Y* YParam);
     Z* ZProp;
 };
于 2021-08-11T12:12:49.540 に答える