ヘッダファイルの二重定義防止 – プログラミング – Home

ヘッダファイルの二重定義防止
 
通知
すべてクリア

[解決済] ヘッダファイルの二重定義防止


デューン
 デューン
(@デューン)
ゲスト
結合: 21年前
投稿: 4
Topic starter  

はじめて投稿させていただきます。
同じヘッダファイルを複数のcppファイルから読み込む場合、
二重の宣言を防ぐために
#pragma once
(VCの場合)

#ifndef _HEADER_H_
#define _HEADER_H_
/*
コード
*/
#endif

とすればよいということはわかったのですが、
うまくいきません。

たとえば
hoge.h
foo.cpp
bar.cpp
とあった場合

//- hoge.h -----------------------------------------------------------------
#ifndef _HOGE_H_
#define _HOGE_H_
int a(){
return 0;
}
#endif

//- foo.cpp -----------------------------------------------------------------
#include hoge.h

void main(void){

}

//- bar.cpp -----------------------------------------------------------------
#include hoge.h

---------------------------------------------------------------------------
ビルドすると
VC6++でも
VC++ .NET2003 でも
「bar.obj : error LNK2005: _a はすでに foo.obj で定義されています」

と出てしまいます。
クラスとメンバ関数は inline展開にしてやると通ったのですが・・・
なにが問題なのでしょうか。
ひとつのソースファイルで
#include hoge.h
#include hoge.h
と二度定義するのは大丈夫だったのですが・・・

環境は
WinowsXP
VisualStudio 6.0
です。
よろしくお願いします。


引用未解決
トピックタグ
島
 島
(@島)
ゲスト
結合: 23年前
投稿: 238
 

リンカーの出した警告(またはエラー報告)だということはお分わりですか?
二(多)重インクルードが問題になるのは普通はコンパイル時のことだと思います

ヘッダーに函数(かんすう、関数)の定義(プロトタイプ宣言でなく)をかいているから
なんじゃないんでしょうか

#include hoge.h とヘッダーを読み込むように指定したソースそれぞれに int a()
というスタチックでない函数が定義しているものだから、コンパイラーは言われた通り
にその函数をコンパイルしますが、リンカーが複数のオブジェクトファイルに同じ名前で
同じ戻り値の型で、同じ引数の並びの函数があることに気付いて親切に教えてくれている
のでしょう


返信引用
デューン
 デューン
(@デューン)
ゲスト
結合: 21年前
投稿: 4
Topic starter  

返答ありがとうございます。

リンカが出している警告だというのは、
objに対しての警告なのでわかります。

ヘッダファイルには
グローバル変数やグローバル関数。
インライン指定(?)以外でのクラスのメンバ関数
というのはできないということなのでしょうか?

どこかでできる。というような記述を見かけたのですが。
以下のような形で用意するしかないということでしょうか?

//- hoge.h -----------------------------------------------------------------
#ifndef _HOGE_H_
#define _HOGE_H_
int a();
extern b;
#endif

//- hoge.cpp -----------------------------------------------------------------
#include hoge.h
int b;
int a();{
return 0;
}

//- foo.cpp -----------------------------------------------------------------
#include hoge.h

void main(void){
b+=2;
}

---------------------------------------------------------------------------


返信引用
島
 島
(@島)
ゲスト
結合: 23年前
投稿: 238
 

宣言と定義との違いはお分かりですか?

>//- hoge.h -----------------------------------------------------------------
>#ifndef _HOGE_H_
>#define _HOGE_H_
>int a();
>extern b;
>#endif

今回の例では宣言しかありませんが下に示す前回の例では

>>//- hoge.h -----------------------------------------------------------------
>>#ifndef _HOGE_H_
>>#define _HOGE_H_
>>int a(){
>> return 0;
>>}
>>#endif

のように函数(かんすう、関数)の定義が書いてありますね
先ほどの説明のどこが分かり難(にく)かったのでしょうか?

>ヘッダファイルには
>グローバル変数やグローバル関数。
>インライン指定(?)以外でのクラスのメンバ関数
>というのはできないということなのでしょうか?
御免なさい、質問の意味がわかりません。
できないとは何が出来ないということなんでしょうか?


返信引用
デューン
 デューン
(@デューン)
ゲスト
結合: 21年前
投稿: 4
Topic starter  

すいません。最後の質問は言葉が足りませんでした。

ヘッダファイル内で、
関数を宣言し、
その関数を複数のソースファイルから
利用することは可能ですか?


返信引用
島
 島
(@島)
ゲスト
結合: 23年前
投稿: 238
 

>ヘッダファイル内で、
>関数を宣言し、
>その関数を複数のソースファイルから
>利用することは可能ですか?

宣言というのは定義とは違い内容(値や振る舞い)について記述しません
型に付いてコンパイラーや読み手に知らせるためのものですから
そういう使い方をするのがヘッダーファイルの役割だと思います
ですから、可能というよりは、そのような使い方をするものでしょう


返信引用
デューン
 デューン
(@デューン)
ゲスト
結合: 21年前
投稿: 4
Topic starter  

なるほど。
たしかにヘッダファイルは
コンパイルしてオブジェクトファイルを作るものではありませんし、
ヘッダファイルには定義を。
宣言はソースファイルに記述すべき。
ということなのですね。

勉強になりました。
お付き合い戴き、ありがとうございました。


返信引用
島
 島
(@島)
ゲスト
結合: 23年前
投稿: 238
 

>ヘッダファイルには定義を。
>宣言はソースファイルに記述すべき。

どうしてそうなるんでしょうか?
私の書き方のどこがいけなかったのでしょうか?
逆なんですけど....

それに、すべきとも書いてないんですけど....


返信引用
通りすがり
 通りすがり
(@通りすがり)
ゲスト
結合: 24年前
投稿: 92
 

>ヘッダファイルには定義を

#defineとかtypedefとかあるので
まぁ間違いではないでしょうな

本人がどういう意味で使っているのかは知りませんが

>ヘッダファイル内で、
>関数を宣言し、
>その関数を複数のソースファイルから
>利用することは可能ですか?

大方これも
「ヘッダーファイルで関数を定義して利用できるか」
の間違いなのでは?
宣言して利用することが可能なのはできているようだし


返信引用
karabiner
 karabiner
(@karabiner)
ゲスト
結合: 21年前
投稿: 5
 

本当にそうすることに意味があるのかを再考すべきだとは思いますが、
この疑問に対しての表面的な回答としては、無名名前空間を使えばいいのではないかと。

=== hoge.h ===

#ifndef _HOGE_H_
#define _HOGE_H_
namespace { // 無名名前空間ここから

int a(){
return 0;
}

} // 無名名前空間ここまで
#endif


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました