前提・実現したいこと
VC++で構造体を使ったプログラムを書いています。
構造体を定義したヘッダーファイルをインクルードした、別のヘッダーファイルからその構造体を返り値に持つ関数の宣言をするとビルドエラーが出てしまいます。
ソースファイルから構造体を定義したヘッダーファイルをインクルードして、構造体を返り値に持つ関数を定義したところ、エラーもなくビルドができました。
発生している問題・エラーメッセージ
重大度レベル コード 説明 プロジェクト ファイル 行 抑制状態 エラー C2461 'msg': コンストラクターに、仮引数が指定されていません。 msg.h エラー C4430 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません。 r_msg.h エラー C2146 構文エラー: ';' が、識別子 'retMsg2' の前に必要です。 r_msg.h エラー C2461 'msg': コンストラクターに、仮引数が指定されていません。 msg.h エラー C4430 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません。 r_msg.h エラー C2146 構文エラー: ';' が、識別子 'retMsg2' の前に必要です。 r_msg.h エラー C2461 'msg': コンストラクターに、仮引数が指定されていません。 msg.h
該当のソースコード
c++
1/** main.cpp **/ 2#include "msg.h" 3 4int main() { 5 6 return 0; 7}
header
1#pragma once 2/** msg.h **/ 3#ifndef _MSG_ 4#define _MSG_ 5#include <string> 6#include "r_msg.h" 7using namespace std; 8 9struct msg { 10 string msg = ""; 11}; 12#endif
header
1#pragma once 2/** r_msg.h **/ 3 4#include "msg.h" 5msg retMsg2();
c++
1/** r_msg.cpp **/ 2#include "r_msg.h" 3 4msg retMsg2() { 5 msg Msg; 6 return Msg; 7}
試したこと
- ソースファイルから構造体を呼び出してもエラーは発生しませんでした。
- 関数の宣言から、変数の宣言に書き換えてみましたが、同じエラーが発生しました。
補足情報(FW/ツールのバージョンなど)
visual studio 2019
c++ 14
windows 10 Home 64bit
/** msg.h **/
#include "r_msg.h"
extern struct msg {
  string msg = "";
};
/** r_msg.h **/
#include "msg.h"
msg retMsg2();//エラーが発生する
相互にインクルードしあって、たぶんこれはエラーになると思うのですが?
msg retMsg2();
の宣言や定義を削除すると正常に動くので、相互インクルードにはなっていないと勝手に判断していたのですが、やはり相互インクルードしてしまっているのでしょうか?
だって、msg.hの冒頭で
#include "r_msg.h"
r_msg.hの冒頭で
#include "msg.h"
これが相互インクルードでなければなんなのでしょう?
ありがとうございます。
たしかに、エラーは発生していませんが、相互インクルードに違いはないと思い、インクルードガードを追加しておきました。
そもそもmsg.hでr_msg.hをインクルードしなきゃいけない理由がないのであって、
msg.hでr_msg.hをインクルードしているのがおかしいのですが。
でも、相互インクルードしてエラーが出ないといしたらそれもおかしい...
msg.h中にわざとエラーを埋め込んだら(例えば#errorで)、ビルド時にちゃんとそのエラーは出ますか?
> インクルードガードを追加しておきました
それ、なにか変じゃありませんか?
msg.h内に#errorを記述したところビルドエラーが発生しました。
msg.hでr_msg.hをインクルードするのはmsg.hからr_msg.hの関数にアクセスしたいためです。
> msg.hからr_msg.hの関数にアクセスしたいためです。
「したい」というあなたの意思は知りませんが、事実として
struct msg {
  string msg = "";
};
はr_msg.hにかかれた内容に一切依存していませんよね?
質問に書いてあるファイル4つで(VisualStudioのIDEなら新たにプロジェクトを作成して)、質問にあるエラーが再現するか再度確認してみてください。そのへんから話がおかしくなっている気がします。
すみません、質問に関係ないと思い省いてしまっていますが、msg.cppからr_msg.cppの関数にアクセスしています。
そのため、msg.hまたはmsg.cppにインクルードを記述しなければならず、msg.hにインクルードを記述しています。
なので、インクルードをしています。
>> インクルードガードを追加しておきました
>それ、なにか変じゃありませんか?
インクルードガードを全文に変更すると、r_msg.hから見るとmsg構造体自体が定義されていないことになってしまうので、こうしています。
> r_msg.hから見るとmsg構造体自体が定義されていないことになってしまうので、こうしています。 
だから、それって変だ、と。
> msg.cppからr_msg.cppの関数にアクセスしています。
> そのため、msg.hまたはmsg.cppにインクルードを記述しなければならず
そこでmsg.hにインクルードを記述するのは適切じゃないでしょう。
>> r_msg.hから見るとmsg構造体自体が定義されていないことになってしまうので、こうしています。
>だから、それって変だ、と。
main.cppから一度、msg.hをインクルードするので、その後r_msg.hからインクルードしてもインクルードガードによってmsg構造体が見えなくなっています。
通常はmain.cppでインクルードしているのでr_msg.hからもアクセスできると思うのですが、私の環境では、msg認識子が見つかりません。
>そのへんから話がおかしくなっている気がします。
一度、VisualStudioから新たにプロジェクトを作成して、このソースを実行してみましたが、同様のエラーが出ています。




