分割コンパイル
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
今回は分割コンパイルについて説明します
分割コンパイルとは複数のC/C++ソースファイルをまとめてひと...
いままではひとつのソースファイル(main.cpp)だけでプログ...
VC++では複数のソースファイル(.cpp)に関数、クラスなどを分...
他のプロジェクトでそのソースファイルを使いまわしたりする...
SIZE(30){ COLOR(#ffaa00){再利用できるよく使う機能などをま...
(正確にいうとソースファイルだけじゃないけど・・・)
プログラムの規模が大きくなってきたときやライブラリを作成...
あるいは複数人で作業を分担するときにはソースファイルを分...
前提としては
SIZE(30){ COLOR(#ffaa00){main関数(もしくはWinMain関数)...
というのはmain関数がプログラム全体の開始となる関数なので
複数のソースファイルにそれぞれmain関数があると「どこから...
なので、ライブラリにはmain関数は含めません
では、早速分割コンパイルをやってみましょう
いつものように空のプロジェクトを作成します
空のプロジェクトの作り方はVC++便利機能で説明しています
まず、ヘッダーファイル(.h)を作ります
ヘッダーファイルとは#include <stdio.h>とかのアレです
フォルダ内で右クリック→新規作成→テキスト(.txt)
でまず、テキストファイルを作成します
&ref(text.GIF);
拡張子が表示されてない人は
Windows XPの人は「ツール」→「フォルダオプション」
Windows Vista、Windows 7の人は「コントロールパネル」内の...
で開き、「表示タブ→登録されている拡張子は表示しない」のチ...
拡張子を表示するようにしてください
この設定をすることで後のファイルの名前の変更で拡張子を変...
ファイルの種類の識別がしやすいのでセキュリティ的にも表示...
&ref(folderop.GIF);
作成したファイルを右クリック→名前の変更で拡張子(.以下)...
ここではtest.hにでもしましょうか
&ref(namechange.GIF);
拡張子はファイルの種類を識別するためのもので
SIZE(30){ COLOR(#ffaa00){実際にはファイルというのは「テキ...
拡張子に惑わされないでください
「テキスト形式」は文字で書かれているファイルのことです
「バイナリ形式」は画像ファイルや音声ファイルなどコンピュ...
広義な意味では文字コードと呼ばれる数値を文字に変換してい...
(文字化けが起きるのは読み込みの文字コードが合わないときに...
プログラムを文字で書く、ソースファイルやヘッダーファイル...
ここまで説明しておいてなんですが、
いちいち、テキストファイルを新規作成して拡張子変更しても...
VC++では簡易的に次の方法でソースファイルやヘッダファイル...
main.cppを作るときとまったく同じです
&ref(DivideSource.GIF);
ここでtest.hを作成してください
また、さらにtest.cppを作成してください
&ref(DivideSource2.GIF);
追加したらそれぞれ次のコードを書いてください
ファイルが複数になると画面分割したほうが見やすくなって便...
画面分割に関してはVC++便利機能を参考にしてください
test.hです
// test.h
#ifndef _TEST_H_
#define _TEST_H_
// 自作関数
void MyFunc();
// 自作クラス
class MyClass{
public:
// コンストラクタ
MyClass();
// デストラクタ
virtual ~MyClass();
};
#endif
test.cppです
// test.cpp
#include "test.h"
#include <stdio.h>
// 自作関数
void MyFunc(){
printf("自作関数\n");
}
// コンストラクタ
MyClass::MyClass(){
printf("自作クラス コンストラクタ\n");
}
// デストラクタ
MyClass::~MyClass(){
printf("自作クラス デストラクタ\n");
}
main.cppです
// main.cpp
#include "test.h"
int main(){
// 自作関数呼び出し
MyFunc();
// 自作クラスインスタンス生成
MyClass myclass;
return 0;
}
書き終わったらソリューションのビルド(F7)を行います
&ref(build2.GIF);
次のように出てきたらビルド成功です
&ref(build.GIF);
上の図でソースファイル(.cpp)毎にコンパイルされることに注...
また、コンパイル後にリンクされていることにも気づいてくだ...
デバック無しで開始で実行できます(Ctrl+F5)
ちなみに、#include "test.h"と""で囲った場合、
プロジェクトのあるディレクトリからの相対パスでヘッダーフ...
よく使う #include <stdio.h>とかの<>で囲った場合
ディレクトリのパスが指定されているところからも探索します
ディレクトリのパスについてはVC++プロジェクトのプロパティの
追加のインクルードディレクトリの項目を参考にしてください
なぜ、うまくいくのかというのをわかりやすく説明するために
簡易的に適当な名前の新しい空のプロジェクトを作り、
次のコードをmain.cppに書いて
#include <stdio.h>
void MyFunc();
int main(){
MyFunc();
return 0;
}
(ビルドでなく)main.cppをコンパイル(CTRL+F7)してください
&ref(compile.GIF);
コンパイルは通ります
&ref(compile2.GIF);
しかし、今度はビルドを通りません
&ref(build3.GIF);
リンカーエラーとなります
これは関数の中身を書いてないのでどのような処理をすればい...
実行ファイルを作成できないのです
実はVC++ではコンパイルが成功したソースファイルは対応した....
その.objファイルにシンボルと呼ばれるものが埋め込まれます
そのシンボルに基づいてリンカーは関数の実装部分と関連付け...
つまり、ヘッダーファイルにはプロトタイプ宣言などを書き
それを#includeして、普通に関数を呼び出す記述をすれば、シ...
どの関数の実装部分を呼び出すかはリンカーが関数の戻り値や...
複数の.objファイル(と.libファイル)から自動的に判別して...
今回は関数やクラスの実装部分はtest.cppに書かれていること...
ゆえにビルドする全てのファイルにおいて
全く同一の戻り値と引数を持つ関数や同名のクラス名が存在し...
ところでtest.hで#ifndefと#defineで定義している部分を
インクルードガードといいます
なぜ、こんなことをする必要があるのか?
というのを知るためには#includeについて知る必要が出てきます
実は#includeはプリコンパイル時(コンパイル前の処理)に
ただ単にファイルをまるごとコピー&ペーストして張り付けて...
気を付けてほしいのは#includeしたファイルに#includeがある...
たとえば、次の場合main.cppをコンパイルすると多重定義エラ...
&ref(include1.GIF);
なぜならば、次のように展開されているからです
&ref(include2.jpg);
つまり同じクラスを多重に宣言してしまうことになるのです
ここでインクルードガードを付けていれば
#ifndef インクルードガード名
#define インクルードガード名
// 関数などの宣言はここにする
#endif
1回め#includeするとき、インクルード名が#defineで定義され
2回め#includeされるとき、#ifndefと#endifで囲まれたところ...
&ref(include3.jpg);
SIZE(30){ COLOR(#ffaa00){インクルードガードはヘッダーファ...
ただし、
SIZE(30){ COLOR(#ffaa00){インクルードガードに使う名前はす...
理由は他のヘッダーファイルが#includeで展開するとき無効化...
これが起きるとエラーの原因を探すのがけっこうめんどうにな...
(基本的にヘッダーファイル名に由来したものをつける習慣を...
また、VC++ではインクルードガードの方法にSIZE(30){ COLOR(#...
これは#includeで多重に同じファイルを展開しないことを
プリコンパイラに知らせているものです
たとえば、test.hは#pragma onceを使って次のように書きなお...
// test.h
#pragma once
// 自作関数
void MyFunc();
// 自作クラス
class MyClass{
public:
// コンストラクタ
MyClass();
// デストラクタ
virtual ~MyClass();
};
ヘッダーファイルの先頭に書けばいいだけです
ただし他のコンパイラ(たとえばlinuxやMacのコンパイラ)では#...
他環境下では#ifndefと#defineを使って書く必要が出てきます
また、たまに拡張子に(.hpp)というのも見かけたりします
これは普通のヘッダーファイル(.h)と変わりません
ただ、実装を含んでいるヘッダーファイル(インライン実装、...
#vote((^ω^)やったお[6],何これwww意味不すぎwww[4...
終了行:
今回は分割コンパイルについて説明します
分割コンパイルとは複数のC/C++ソースファイルをまとめてひと...
いままではひとつのソースファイル(main.cpp)だけでプログ...
VC++では複数のソースファイル(.cpp)に関数、クラスなどを分...
他のプロジェクトでそのソースファイルを使いまわしたりする...
SIZE(30){ COLOR(#ffaa00){再利用できるよく使う機能などをま...
(正確にいうとソースファイルだけじゃないけど・・・)
プログラムの規模が大きくなってきたときやライブラリを作成...
あるいは複数人で作業を分担するときにはソースファイルを分...
前提としては
SIZE(30){ COLOR(#ffaa00){main関数(もしくはWinMain関数)...
というのはmain関数がプログラム全体の開始となる関数なので
複数のソースファイルにそれぞれmain関数があると「どこから...
なので、ライブラリにはmain関数は含めません
では、早速分割コンパイルをやってみましょう
いつものように空のプロジェクトを作成します
空のプロジェクトの作り方はVC++便利機能で説明しています
まず、ヘッダーファイル(.h)を作ります
ヘッダーファイルとは#include <stdio.h>とかのアレです
フォルダ内で右クリック→新規作成→テキスト(.txt)
でまず、テキストファイルを作成します
&ref(text.GIF);
拡張子が表示されてない人は
Windows XPの人は「ツール」→「フォルダオプション」
Windows Vista、Windows 7の人は「コントロールパネル」内の...
で開き、「表示タブ→登録されている拡張子は表示しない」のチ...
拡張子を表示するようにしてください
この設定をすることで後のファイルの名前の変更で拡張子を変...
ファイルの種類の識別がしやすいのでセキュリティ的にも表示...
&ref(folderop.GIF);
作成したファイルを右クリック→名前の変更で拡張子(.以下)...
ここではtest.hにでもしましょうか
&ref(namechange.GIF);
拡張子はファイルの種類を識別するためのもので
SIZE(30){ COLOR(#ffaa00){実際にはファイルというのは「テキ...
拡張子に惑わされないでください
「テキスト形式」は文字で書かれているファイルのことです
「バイナリ形式」は画像ファイルや音声ファイルなどコンピュ...
広義な意味では文字コードと呼ばれる数値を文字に変換してい...
(文字化けが起きるのは読み込みの文字コードが合わないときに...
プログラムを文字で書く、ソースファイルやヘッダーファイル...
ここまで説明しておいてなんですが、
いちいち、テキストファイルを新規作成して拡張子変更しても...
VC++では簡易的に次の方法でソースファイルやヘッダファイル...
main.cppを作るときとまったく同じです
&ref(DivideSource.GIF);
ここでtest.hを作成してください
また、さらにtest.cppを作成してください
&ref(DivideSource2.GIF);
追加したらそれぞれ次のコードを書いてください
ファイルが複数になると画面分割したほうが見やすくなって便...
画面分割に関してはVC++便利機能を参考にしてください
test.hです
// test.h
#ifndef _TEST_H_
#define _TEST_H_
// 自作関数
void MyFunc();
// 自作クラス
class MyClass{
public:
// コンストラクタ
MyClass();
// デストラクタ
virtual ~MyClass();
};
#endif
test.cppです
// test.cpp
#include "test.h"
#include <stdio.h>
// 自作関数
void MyFunc(){
printf("自作関数\n");
}
// コンストラクタ
MyClass::MyClass(){
printf("自作クラス コンストラクタ\n");
}
// デストラクタ
MyClass::~MyClass(){
printf("自作クラス デストラクタ\n");
}
main.cppです
// main.cpp
#include "test.h"
int main(){
// 自作関数呼び出し
MyFunc();
// 自作クラスインスタンス生成
MyClass myclass;
return 0;
}
書き終わったらソリューションのビルド(F7)を行います
&ref(build2.GIF);
次のように出てきたらビルド成功です
&ref(build.GIF);
上の図でソースファイル(.cpp)毎にコンパイルされることに注...
また、コンパイル後にリンクされていることにも気づいてくだ...
デバック無しで開始で実行できます(Ctrl+F5)
ちなみに、#include "test.h"と""で囲った場合、
プロジェクトのあるディレクトリからの相対パスでヘッダーフ...
よく使う #include <stdio.h>とかの<>で囲った場合
ディレクトリのパスが指定されているところからも探索します
ディレクトリのパスについてはVC++プロジェクトのプロパティの
追加のインクルードディレクトリの項目を参考にしてください
なぜ、うまくいくのかというのをわかりやすく説明するために
簡易的に適当な名前の新しい空のプロジェクトを作り、
次のコードをmain.cppに書いて
#include <stdio.h>
void MyFunc();
int main(){
MyFunc();
return 0;
}
(ビルドでなく)main.cppをコンパイル(CTRL+F7)してください
&ref(compile.GIF);
コンパイルは通ります
&ref(compile2.GIF);
しかし、今度はビルドを通りません
&ref(build3.GIF);
リンカーエラーとなります
これは関数の中身を書いてないのでどのような処理をすればい...
実行ファイルを作成できないのです
実はVC++ではコンパイルが成功したソースファイルは対応した....
その.objファイルにシンボルと呼ばれるものが埋め込まれます
そのシンボルに基づいてリンカーは関数の実装部分と関連付け...
つまり、ヘッダーファイルにはプロトタイプ宣言などを書き
それを#includeして、普通に関数を呼び出す記述をすれば、シ...
どの関数の実装部分を呼び出すかはリンカーが関数の戻り値や...
複数の.objファイル(と.libファイル)から自動的に判別して...
今回は関数やクラスの実装部分はtest.cppに書かれていること...
ゆえにビルドする全てのファイルにおいて
全く同一の戻り値と引数を持つ関数や同名のクラス名が存在し...
ところでtest.hで#ifndefと#defineで定義している部分を
インクルードガードといいます
なぜ、こんなことをする必要があるのか?
というのを知るためには#includeについて知る必要が出てきます
実は#includeはプリコンパイル時(コンパイル前の処理)に
ただ単にファイルをまるごとコピー&ペーストして張り付けて...
気を付けてほしいのは#includeしたファイルに#includeがある...
たとえば、次の場合main.cppをコンパイルすると多重定義エラ...
&ref(include1.GIF);
なぜならば、次のように展開されているからです
&ref(include2.jpg);
つまり同じクラスを多重に宣言してしまうことになるのです
ここでインクルードガードを付けていれば
#ifndef インクルードガード名
#define インクルードガード名
// 関数などの宣言はここにする
#endif
1回め#includeするとき、インクルード名が#defineで定義され
2回め#includeされるとき、#ifndefと#endifで囲まれたところ...
&ref(include3.jpg);
SIZE(30){ COLOR(#ffaa00){インクルードガードはヘッダーファ...
ただし、
SIZE(30){ COLOR(#ffaa00){インクルードガードに使う名前はす...
理由は他のヘッダーファイルが#includeで展開するとき無効化...
これが起きるとエラーの原因を探すのがけっこうめんどうにな...
(基本的にヘッダーファイル名に由来したものをつける習慣を...
また、VC++ではインクルードガードの方法にSIZE(30){ COLOR(#...
これは#includeで多重に同じファイルを展開しないことを
プリコンパイラに知らせているものです
たとえば、test.hは#pragma onceを使って次のように書きなお...
// test.h
#pragma once
// 自作関数
void MyFunc();
// 自作クラス
class MyClass{
public:
// コンストラクタ
MyClass();
// デストラクタ
virtual ~MyClass();
};
ヘッダーファイルの先頭に書けばいいだけです
ただし他のコンパイラ(たとえばlinuxやMacのコンパイラ)では#...
他環境下では#ifndefと#defineを使って書く必要が出てきます
また、たまに拡張子に(.hpp)というのも見かけたりします
これは普通のヘッダーファイル(.h)と変わりません
ただ、実装を含んでいるヘッダーファイル(インライン実装、...
#vote((^ω^)やったお[6],何これwww意味不すぎwww[4...
ページ名: