
いつもお世話になっています。
MFCでCプログラミングをしています。
ヘッダファイルの2重定義防止のために、
ヘッダファイル全体を下記のように
囲みました。
<aaa.h>
#ifndef AAA
#define AAA
#define PI 3.141592
void Func();
int wa(int a, int b){
return a+b;
}
#endif
ビルドしたところ、
関数宣言(Func)や#define部分(PI)については、
2重定義が防止されているようなのですが、
関数の実体部分(関数wa)については、
2重定義防止機能が働かず、
***.obj : error LNK2005:
"int __cdecl wa(int a, int b)"
は既に ***.obj で定義されています。
というリンクエラーが表示されます。
関数の種類や
ヘッダファイル内の宣言の順番を
いろいろ変えてみたのですが同じ結果でした。
ここで、このヘッダファイルの先頭に
#pragma onceを使用すると
このリンクエラーは回避されるのですが、
他コンパイラとの互換性の観点から、
#pragma once以外の方法で実現する必要があるので、
困っています。
URLを検索してみたのですが、
このような特殊な場合について記述されているものは
見つけられませんでした。
どなたか解決法又はヒントをご教示頂ければ
ありがたいです。
よろしくお願いします。
No.2ベストアンサー
- 回答日時:
二重インクルードは防止できています。
ただし、あくまで1つのコンパイル単位の中での話です。エラー内容から察すると、2つ以上のソースファイルでaaa.hをインクルードしていますね?コンパイル時点ではエラーにはならずに複数のobjファイルが生成されますが、リンク時にエラーが発生します。これは、リンク実行時に関数waの定義が複数のモジュールで発見されるためです。このようなエラーを防ぐため、通常、ヘッダファイルで関数の定義は行わず、その代わりに
extern int wa(int a, int b);
のように宣言だけを記述します。関数定義はどこかのソースファイルで1回だけ行います。
No.4
- 回答日時:
#2の方の通りかと思います。
aaa.hファイルが問題のヘッダーファイルとして、
ソースファイルがa.c, b.cの2つあるとすると
a.cでは、
#inlucde "aaa.h"
......
b.cでも
#include "aaa.h"
......
とされていると思います。
すると2つのソースから作成されるa.obj,b.objそれぞれに
関数waが定義されており、しかもグローバルなスコープです。
よって、リンク時にwaが2つあるのでエラーになっていると思います。
対処としても、#2の方と同じく
関数waはどこかのソースに実体を記述し、ヘッダーファイルに
関数のプロトタイプを記述するのが通常です。
どうしてもヘッダーファイルに関数の実体を記述したいのでしたら
スコープをstaticにすればエラーを回避できるでしょう
static int wa(int a, int b){
return a+b;
}
でもこれは普通じゃないです。
丁寧な解説を頂き、
エラー原因のメカニズムが良く分かりました。
最終的には、
普通でない方法は辞めることにし、
うまくビルド成功しました。
ご教示ありがとうございました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
2重定義って??
-
visualstudio C# テキストボッ...
-
DWORDの実際の型は何でしょうか
-
構造体の要素すべてに対する四...
-
C++デバックエラーについて詳し...
-
C++ Builderでのpublic変数の扱...
-
C++でboolにintの値を代入する...
-
変数の型を定義しなかった場合...
-
コンパイルすると error C1083 ...
-
intとINTの違いは?
-
atoi() 実行エラー
-
ハンドルされていない例外が発...
-
【#define】 defineで定義した...
-
GCCで暗黙の型変換の警告を出し...
-
C言語で分割ファイル先の関数を...
-
関数名 (type *)
-
Aの値からBの値を除するとは??
-
信頼区間の1.96や1.65ってどこ...
-
c languageで 簡単な質問があ...
-
エクセルで可視セルにのみ値貼...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
main.c:7:43: warning: implici...
-
long型の定数の末尾にLを付ける...
-
DWORDの実際の型は何でしょうか
-
visualstudio C# テキストボッ...
-
2重定義って??
-
C++のfor文について
-
変数の型を定義しなかった場合...
-
ハンドルされていない例外が発...
-
intとINTの違いは?
-
C++でboolにintの値を代入する...
-
構造体の要素すべてに対する四...
-
プログラムの中で別のmainを呼...
-
エラー「invalid conversion fr...
-
GCCで暗黙の型変換の警告を出し...
-
【#define】 defineで定義した...
-
sshdログの意味
-
DDVによるメッセージの変更
-
typedef enumの使い方を教えて...
-
構造体を生成時にわざわざ初期...
-
DLLでLIBファイルが作成されない
おすすめ情報