ライブラリのようなものをつくりたい
- MoNoQLoREATOR
- 記事: 284
- 登録日時: 13年前
- 住所: 東京
ライブラリのようなものをつくりたい
ある一つのヘッダファイルをインクルードすることで、そのヘッダファイルに定義されている様々な関数(やクラス等)を扱うことができるようにしたいと考えています。
正確には、「関数(やクラス等)が定義されているヘッダファイル」へのインクルード文が記述されている「ある一つのヘッダファイル」を読み込むことで実現させたいという状況です。
しかし以下のようにすると『main.obj : error LNK2005: "void __cdecl funcB(void)" (?funcB@@YAXXZ) は既に hoge.obj で定義されています』というエラーが出てしまいます。
main.cpp hoge.cpp head.h A.h B.h C.h
どうしたらよいのでしょうか。
ご教授よろしくお願い致します。
正確には、「関数(やクラス等)が定義されているヘッダファイル」へのインクルード文が記述されている「ある一つのヘッダファイル」を読み込むことで実現させたいという状況です。
しかし以下のようにすると『main.obj : error LNK2005: "void __cdecl funcB(void)" (?funcB@@YAXXZ) は既に hoge.obj で定義されています』というエラーが出てしまいます。
main.cpp hoge.cpp head.h A.h B.h C.h
どうしたらよいのでしょうか。
ご教授よろしくお願い致します。
最後に編集したユーザー MoNoQLoREATOR on 2012年2月23日(木) 19:15 [ 編集 1 回目 ]
Re: ライブラリのようなものをつくりたい
✜ で C ご ✜
: す + 注 :
¦ か + 文 ¦
: ? Is the は :
✜ order C++? ✜
: す + 注 :
¦ か + 文 ¦
: ? Is the は :
✜ order C++? ✜
糸冬
――――――――
制作・著作 NHK
――――――――
制作・著作 NHK
- MoNoQLoREATOR
- 記事: 284
- 登録日時: 13年前
- 住所: 東京
Re: ライブラリのようなものをつくりたい
>>loweさん
「エラーが出てしまうケースとして、このようなケースがありますが、どうすればよいでしょう?」と聞くためだけにhoge.cppをつくったので、実際には何も定義していません。(hoge.cppでhead.hをインクルードしなければこのエラーは起こりません。つまりこのエラーは、複数のファイルでhead.hがインクルードされた場合に発生するようです。)
「エラーが出てしまうケースとして、このようなケースがありますが、どうすればよいでしょう?」と聞くためだけにhoge.cppをつくったので、実際には何も定義していません。(hoge.cppでhead.hをインクルードしなければこのエラーは起こりません。つまりこのエラーは、複数のファイルでhead.hがインクルードされた場合に発生するようです。)
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 13年前
- 住所: 東海地方
- 連絡を取る:
Re: ライブラリのようなものをつくりたい
例えば
だと funcA()の実体の定義ということになるので、このヘッダを複数のcppにインクルードすると多重定義になります。
[補足]
ヘッダだけインクルードして、プログラムを組み込んでしまう方法としては
1.本当にライブラリにしてしまう。
2.定義か参照か切り分ければ良いので龍神録のようにGLOBAL_INSTANCEの定義有無で切り分ける。
3.クラスの宣言だけを行いインスタンスをヘッダでは生成しない。つまりヘッダには単なる関数の定義は書かない。
[補足]
ヘッダだけインクルードして、プログラムを組み込んでしまう方法としては
1.本当にライブラリにしてしまう。
2.定義か参照か切り分ければ良いので龍神録のようにGLOBAL_INSTANCEの定義有無で切り分ける。
3.クラスの宣言だけを行いインスタンスをヘッダでは生成しない。つまりヘッダには単なる関数の定義は書かない。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: ライブラリのようなものをつくりたい
ややバッドノウハウ的ではありますが...
ヘッダファイルの中で定義する関数は、すべてインライン関数か関数テンプレートにしましょう。
それで解決するはずです。
ヘッダファイルの中で定義する関数は、すべてインライン関数か関数テンプレートにしましょう。
それで解決するはずです。
- MoNoQLoREATOR
- 記事: 284
- 登録日時: 13年前
- 住所: 東京
Re: ライブラリのようなものをつくりたい
>>softya(ソフト屋)さん
>>たかぎさん
返信ありがとうございます。
とりあえずソフト屋さんの2番目の方法で解決してみることにしました。
しかし、以下のようにしてみても、同じエラーが出ました。
main.cpp hoge.cpp head.h
A.h
B.h
C.h
>>たかぎさん
返信ありがとうございます。
とりあえずソフト屋さんの2番目の方法で解決してみることにしました。
しかし、以下のようにしてみても、同じエラーが出ました。
main.cpp hoge.cpp head.h
#ifdef FW_FUNCTION
#define FUNCTION
#else
#define FUNCTION extern
#endif
#include "A.h"
#include "B.h"
#include "C.h"
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 13年前
- 住所: 東海地方
- 連絡を取る:
Re: ライブラリのようなものをつくりたい
ちがいますよ。
私の書き方たが悪かったですかね。
って事です。
私の書き方たが悪かったですかね。
って事です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: ライブラリのようなものをつくりたい
ああ、そうでしたか。すみません。MoNoQLoREATOR さんが書きました:>>loweさん
「エラーが出てしまうケースとして、このようなケースがありますが、どうすればよいでしょう?」と聞くためだけにhoge.cppをつくったので、実際には何も定義していません。
たかぎさんがインライン化を勧めているのでそれでもいいと思いますが、そもそもライブラリにするならヘッダファイルに実体を作ってしまうこと自体あまりよろしく無いと思います。
ヘッダファイルに実体を作らなければいい話ですし、hoge.cppをサンプルに用意したという事はヘッダに全て詰め込まなくてはいけないという状況でも無いと思いますから。
あと、単なる誤記でしょうが ですね
✜ で C ご ✜
: す + 注 :
¦ か + 文 ¦
: ? Is the は :
✜ order C++? ✜
: す + 注 :
¦ か + 文 ¦
: ? Is the は :
✜ order C++? ✜
糸冬
――――――――
制作・著作 NHK
――――――――
制作・著作 NHK
- MoNoQLoREATOR
- 記事: 284
- 登録日時: 13年前
- 住所: 東京
Re: ライブラリのようなものをつくりたい
>>softya(ソフト屋)さん
>>たかぎさん
>>loweさん
返信ありがとうございます。
たかぎさんにインライン関数を進めて頂いておりますが、あまり使う気分になりません。インライン関数を調べてみたのですが、#defineを使用したときのように、該当部分がコンパイル前に置き換えられるてしまうのですよね?なんだか非効率的な気がします。
それと、私は「ライブラリのようでライブラリでない物」を作る予定です。ライブラリと言うと堅苦しいイメージがあるので・・・。気分の問題です。
さて、下記のように修正してみるとエラーは出なくなりました。
解決しました。本当にありがとうございました。
main.cpp hoge.cpp head.h A.h B.h C.h
>>たかぎさん
>>loweさん
返信ありがとうございます。
たかぎさんにインライン関数を進めて頂いておりますが、あまり使う気分になりません。インライン関数を調べてみたのですが、#defineを使用したときのように、該当部分がコンパイル前に置き換えられるてしまうのですよね?なんだか非効率的な気がします。
それと、私は「ライブラリのようでライブラリでない物」を作る予定です。ライブラリと言うと堅苦しいイメージがあるので・・・。気分の問題です。
さて、下記のように修正してみるとエラーは出なくなりました。
解決しました。本当にありがとうございました。
main.cpp hoge.cpp head.h A.h B.h C.h
Re: ライブラリのようなものをつくりたい
使いたくないなら使わないでまったく問題は有りません.MoNoQLoREATOR さんが書きました: たかぎさんにインライン関数を進めて頂いておりますが、あまり使う気分になりません。インライン関数を調べてみたのですが、#defineを使用したときのように、該当部分がコンパイル前に置き換えられるてしまうのですよね?なんだか非効率的な気がします。
ただ,インライン関数がいつも非効率かというと,まったくそうでは有りません.
例えば, というクラスを考えます.
クラスの中で関数を定義しますと,暗黙にインライン化を要請することになりますので,get_x関数はほとんどの場合インライン化されます.
もし,get_xがインライン化されない場合,get_xの呼び出しは例えば
- 戻り番地をスタックに積む
- thisポインタをスタックに積む
- get_xにジャンプ(ジャンプするので,CPUのパイプラインはフラッシュされてしまう)
- thisポインタにx_のオフセットを加算して,そのアドレスからデータをロード
- ロードした値をeaxレジスタに格納
- get_xから戻る
インライン化されるとコードサイズが肥大化してしまう,という懸念はまさにその通りです.インライン化はコードサイズを少し増やす代わりに,実行速度を上げることができる可能性がある技術です.
Re: ライブラリのようなものをつくりたい
実はそうでもないんですよ。beatle さんが書きました:インライン化されるとコードサイズが肥大化してしまう,という懸念はまさにその通りです.インライン化はコードサイズを少し増やす代わりに,実行速度を上げることができる可能性がある技術です.
引数のコピーや関数のコール&リターンのコードが、関数の実体のサイズを上回るときはもちろん、そうでない場合でもインライン関数のほうが小さくなることがあります。
というのは、関数を呼び出すと、その関数から例外が送出される可能性を考慮しないといけないわけですが、インライン関数の場合は中が丸見えですので、例外が送出される可能性がまったくなければそのことがコンパイラにわかります。
結果として、例外にからんだコードが生成されなくても済むようになります。
あるいは、関数の枠を超えた最適化ができますので、極端な場合、関数の処理をコンパイル時に解決してしまうことさえできるのです。
もっとも、何でもかんでもインライン関数にすればよいというわけではありません。
テンプレートと組み合わせれば、インラインではない関数もヘッダファイルに定義を記述することが可能になります。
ヘッダファイルに定義を全部入れることの便利さは、Boost C++ Librariesなどのテンプレートライブラリを使ったことがある人なら容易に理解できるはずです。
- MoNoQLoREATOR
- 記事: 284
- 登録日時: 13年前
- 住所: 東京
Re: ライブラリのようなものをつくりたい
>>beatleさん
>>たかぎさん
非効率的だという言い方には語弊がありましたね。
お言葉をお借りしますと、「コードの肥大化」が気に入らないというのが理由です。
関数があまりにも短い場合はインライン関数にする予定ですよ。
>>たかぎさん
非効率的だという言い方には語弊がありましたね。
お言葉をお借りしますと、「コードの肥大化」が気に入らないというのが理由です。
関数があまりにも短い場合はインライン関数にする予定ですよ。