
いつもお世話になっています。
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で質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# C言語の課題が出たのですが自力でやっても分かりませんでした。 要素数がnであるint型の配列v2の並 3 2022/11/19 17:41
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# 変数のスコープ 5 2023/05/27 17:50
- 大学・短大 C言語線形リストの問題です 3 2022/12/22 00:45
- C言語・C++・C# C言語 3 2022/10/04 15:07
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# C言語初心者です、、、お助けください 2 2023/03/14 20:08
- C言語・C++・C# leetcode 155 minstack 1 2022/05/07 16:43
- C言語・C++・C# c言語でユーザ関数を利用して入力された文字列を反転させるプログラムを作りたいです。 3 2023/01/29 19:47
このQ&Aを見た人はこんなQ&Aも見ています
-
【gcc・cygwin】multiple definitionエラーの解決法
C言語・C++・C#
-
2重定義って??
C言語・C++・C#
-
multiple definitionというエラー
C言語・C++・C#
-
-
4
1 つ以上の複数回定義されているシンボルが見つかりました
C言語・C++・C#
-
5
CStringの文字列検索&抜き出しについて
C言語・C++・C#
-
6
構造体のextern方法
C言語・C++・C#
-
7
構文エラー;"が型の前にありませんとは、どうしたら解決できるのですか。"
C言語・C++・C#
-
8
既定のコンストラクタがない?
C言語・C++・C#
-
9
エクセルのデータグループ化の際に貼り付けた図だけ一緒に折りたたんでくれません!
Windows Vista・XP
-
10
C言語でヘッダファイルにグローバル変数を宣言する
C言語・C++・C#
-
11
別ファイルの構造体の値を読み込む、変えるには?2
C言語・C++・C#
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
DWORDの実際の型は何でしょうか
-
関数の実体定義にヘッダファイ...
-
enumについて
-
ベクターのpush_back()で2変数...
-
2重定義って??
-
main.c:7:43: warning: implici...
-
visualstudio C# テキストボッ...
-
C++ クラスをメンバにもつクラ...
-
void func( void )について
-
変数の型を定義しなかった場合...
-
long型の定数の末尾にLを付ける...
-
typedef enumの使い方を教えて...
-
戻り値の型??
-
スレッドのスケジューリングポ...
-
相互参照するクラス、俺こんな...
-
!とキャスト
-
C++のfor文について
-
間違っていないような気がする...
-
DLLのLPSTR 項目の戻り値の取得...
-
【#define】 defineで定義した...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
DWORDの実際の型は何でしょうか
-
visualstudio C# テキストボッ...
-
long型の定数の末尾にLを付ける...
-
C++のfor文について
-
C++でboolにintの値を代入する...
-
2重定義って??
-
main.c:7:43: warning: implici...
-
typedef enumの使い方を教えて...
-
プログラムの中で別のmainを呼...
-
変数の型を定義しなかった場合...
-
関数の実体定義にヘッダファイ...
-
ハンドルされていない例外が発...
-
構造体の要素すべてに対する四...
-
C言語のコンパイルエラー
-
DLLでLIBファイルが作成されない
-
sshdログの意味
-
DLLのLPSTR 項目の戻り値の取得...
-
enumについて
-
VC6でlong longでエラー?
-
【#define】 defineで定義した...
おすすめ情報