[解決済み】C++のforward宣言とは何ですか?
質問
で。 http://www.learncpp.com/cpp-tutorial/19-header-files/
を記載しています。
add.cpp:
int add(int x, int y)
{
return x + y;
}
main.cppです。
#include <iostream>
int add(int x, int y); // forward declaration using function prototype
int main()
{
using namespace std;
cout << "The sum of 3 and 4 is " << add(3, 4) << endl;
return 0;
}
コンパイラが " が何であるかを知ることができるように、前方宣言を使用しました。
add
をコンパイルするとき、" はmain.cpp
. 先に述べたように、別のファイルにある関数を使いたいたびに前方宣言を書くのは、すぐに面倒になります。
"の説明をお願いします。
前方宣言
さらに?で使用すると何が問題なのでしょうか?
main()
関数を使用できますか?
どのように解決するのですか?
C++でforward-declareが必要な理由
コンパイラは、あなたがスペルミスをしたり、関数に渡す引数の数を間違えたりしていないことを確かめたいのです。そのため、コンパイラは'add'(あるいは他の型、クラス、関数)を使用する前に、まずその宣言を確認するように要求している。
これにより、コンパイラはコードの検証をより適切に行うことができ、未解決の部分を整理して、見た目がきれいなオブジェクトファイルを生成できるようになります。もし、前方宣言する必要がなかったら、コンパイラはオブジェクトファイルを生成する際に、その中に関数
add
である可能性があります。そしてリンカーは、どの
add
を呼び出そうとしたとき、実際に呼び出したのは
add
関数が別のオブジェクトファイル内にある場合、リンカは add を使って
dll
または
exe
. リンカが間違った
add
. 例えば、あなたが
int add(int a, float b)
しかし、リンカはすでに存在する
int add(int a, int b)
で、それが正しいものだと思い、代わりにそれを使っています。あなたのコードはコンパイルされますが、あなたが期待していたようなことはできません。
そのため、コンパイラは、物事を明確にし、推測などを避けるために、使用する前にすべてを宣言することを義務づけています。
宣言と定義の違い
余談だが、宣言と定義の違いを知っておくことは重要である。 関数の場合は、戻り値の型、呼び出し方法、メソッド名、引数、およびその型がこれにあたります。しかし、メソッドのコードは必要ありません。定義には、宣言と、関数のコードも必要です。
フォワード宣言でビルド時間を大幅に短縮する方法
ある関数の宣言を、現在の
.cpp
または
.h
ファイルを作成する際に、すでに関数の宣言が含まれているヘッダを#includeすることで、その関数を使用することができます。しかし、これはコンパイルを遅くする可能性があります。
#include
ヘッダを
.h
の代わりに
.cpp
を #include しているものはすべて、あなたのプログラムの
.h
を書くと、あなたが書いたすべてのヘッダーも#includeされてしまうのです。突然、1つか2つの関数を使いたいだけなのに、コンパイラは何ページものコードを#includeしてしまい、コンパイルする必要があるのです。これを避けるには、前方宣言を使用して、ファイルの先頭で関数の宣言を自分で入力すればいいのです。数個の関数を使うだけなら、ヘッダを常に#includeするのに比べて、コンパイルが本当に速くなる。大規模なプロジェクトでは、1時間以上のコンパイル時間を数分に短縮できるかもしれません。
2つの定義が互いに利用しあうような循環的な参照を解除する。
さらに、前方宣言はサイクルを断ち切るのに役立ちます。これは、2つの関数が互いに利用しあおうとしている状態です。このような場合(これは完全に正しい行為です)、次のようにします。
#include
というヘッダーファイルがありますが、そのヘッダーファイルは
#include
そのヘッダがもう一つのヘッダを#includeし、そのヘッダが今書いているヘッダを#includeしています。それぞれのヘッダーファイルが他のヘッダーを再インクルードしようとする、鶏と卵のような状況に陥ってしまうのです。これを解決するには、必要な部分を一方のファイルで前方排他的に宣言し、そのファイルから#includeを除外すればいいのです。
例
ファイル Car.h
#include "Wheel.h" // Include Wheel's definition so it can be used in Car.
#include <vector>
class Car
{
std::vector<Wheel> wheels;
};
ファイル Wheel.h
ふむふむ・・・宣言の
Car
が必要です。
Wheel
へのポインタを持っています。
Car
が、しかし
Car.h
は、コンパイラーエラーになるため、ここに含めることはできません。もし
Car.h
をインクルードした場合、その後に
Wheel.h
を含むことになります。
Car.h
が含まれます。
Wheel.h
このままでは永遠に続くので、コンパイラはエラーを発生させます。解決策は、前方に
Car
の代わりに
class Car; // forward declaration
class Wheel
{
Car* car;
};
もしクラス
Wheel
のメソッドを呼び出す必要があるメソッドを持っていました。
Car
で定義されている場合、それらのメソッドは
Wheel.cpp
と
Wheel.cpp
を含めることができるようになりました。
Car.h
を使用すると、サイクルが発生しません。
関連
-
[解決済み】LLVMで暗黙のうちに削除されたコピーコンストラクタの呼び出し
-
[解決済み】C++コンパイルタイムエラー:数値定数の前に期待される識別子
-
[解決済み】「Expected '(' for function-style cast or type construction」エラーの意味とは?
-
[解決済み】エラー:不完全な型へのメンバーアクセス:前方宣言の
-
[解決済み] explicit キーワードの意味は?
-
[解決済み] ルール・オブ・スリーとは?
-
[解決済み] コピーアンドスワップ慣用句とは?
-
[解決済み] ムーブセマンティクスとは何ですか?
-
[解決済み] フォワード宣言はどのような場合に使用できますか?
-
[解決済み】C/C++の"-->"演算子とは何ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] テスト
-
[解決済み】非静的メンバ関数への参照を呼び出す必要がある
-
[解決済み] error: 'ostream' does not name a type.
-
[解決済み】「corrupted size vs. prev_size」glibc エラーを理解する。
-
[解決済み】C++プログラムでのコンソールの一時停止
-
[解決済み】「Expected '(' for function-style cast or type construction」エラーの意味とは?
-
[解決済み】クラスのコンストラクタへの未定義参照、.cppファイルの修正も含む
-
[解決済み] to_string は std のメンバーではない、と g++ が言っている (mingw)
-
[解決済み】警告 - 符号付き整数式と符号なし整数式の比較
-
[解決済み】Eclipse IDEでC++エラー「nullptrはこのスコープで宣言されていません」が発生する件