質問するログイン新規登録
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

include

あるファイルで定義された関数や処理を、別のファイル上でも使用できるようにするプロセスをincludeと呼びます。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

初心者

初心者は、プログラミングやITに不慣れな方が、基礎的な知識やスキルを身につける際に直面する疑問や課題に関する投稿に使用されます。入門書や学習サイトで学び始めた方、初めての開発環境構築でつまずいた方などに向けた質問が多く見られます。

意見交換

16回答

1501閲覧

不要なincludeを書いている理由

fana

総合スコア12256

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

include

あるファイルで定義された関数や処理を、別のファイル上でも使用できるようにするプロセスをincludeと呼びます。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

初心者

初心者は、プログラミングやITに不慣れな方が、基礎的な知識やスキルを身につける際に直面する疑問や課題に関する投稿に使用されます。入門書や学習サイトで学び始めた方、初めての開発環境構築でつまずいた方などに向けた質問が多く見られます。

2グッド

3クリップ

投稿2025/07/29 03:05

編集2025/07/31 02:08

2

3

C++初心者です.

下記のコード例のような場合……
関数の実装を書いている Func.cpp では,関数の宣言が書かれている Func.h を include する必要は無いです.

無いのですが……
自分は 何故か Func.cpp#include "Func.h" を書いてしまいます.
でも,その理由が自分でもよくわかりません.

  • Func.cpp なるファイルを用意した時点で半ば機械的に書いてるだけ?(単なる習慣?)
  • 「対応しているヘッダがこれだよ」っていうのを明記したいとかそういう何か?
    あるいは,IDEでincludeの記述箇所からヘッダに飛べるみたいな利便性?
  • オーバーロード不可能な形でシグネチャを書き損じた場合とかにコンパイルエラーが欲しい?(限定的だなぁ)
  • ???

考え出したら何もかもわからなくなってきました.

皆さん,このような場合,

  • #include "Func.h" を書きますか? 書きませんか?
  • その理由って何でしょうか?
    (まぁ,書かない側の理由は「要らないから」になるのでしょうけど)

C++

1//[Func.h] 2#pragma once 3 4class X; 5 6int Func1( int, double ); 7int Func2( const X& );

C++

1//[Func.cpp] 2#include "Func.h" //←※コレは不必要なinclude※ 3#include "X.h" //(これはclass X の定義が書かれているやつ) 4 5int Func1( int, double ){ /*...(略)*/ } 6int Func2( const class X& ){ /*...(Xの定義が必要な記述.略)*/ }
tetuhiroshi, Mr.KK👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

回答16

#1

hiroki-o

総合スコア1528

投稿2025/07/29 12:59

あとで別の*.cppからFunc1Func2を呼び出せるように...って、mainはどこにある前提?
そもそも、fanaさんはC++初心者ではないし、この引っかけ問題は難しい...

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

#2

YouheiSakurai

総合スコア6155

投稿2025/07/29 13:29

私は、小さなプログラム&使い捨てる心づもり&自分しか読まないコードだとヘッダファイルは用意しません。そうでなければとりあえずお行儀良くヘッダファイルを準備します。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

#3

fana

総合スコア12256

投稿2025/07/30 01:25

編集2025/07/30 01:29

あとで別の*.cppからFunc1、Func2を呼び出せるように...って、mainはどこにある前提?

おっしゃる通り, Func1()Func2() は別の個所から使われる想定の話です.
引っかけ(?) とかではなく,ごくごくふつーのやつです.

Func1()Func2() の実装者としては 「他所で使うのに宣言が欲しいだろうから → それを書いたヘッダを用意したぜ!」っていう.

main() 関数から使うとしたら以下のような.

C++

1//[別の翻訳単位] 2#include "Func.h" //関数の宣言が必要なので,用意されてるヘッダをありがたく使わせてもらうよ 3 4int main() 5{ 6 /* Func1() とか Func2() とかを使うよ */ 7}

要は,こんな感じで,この Func.h ってのは「他の場所で」include するための物として用意しているものなわけで,少なくともこの例ではコレを Func.cpp という翻訳単位が include する必要がない.
……んだけど,なぜか(体が勝手に?) include 書いちゃうんだよなぁ,なんでかなぁ……っていうだけの話です.
( 「 .cpp と対になる(?)感じで書いたヘッダ内に .cpp の実装が必要とする記述が無い」っていう状況というのがレアケースだから,そういうの考えずに脳死的に include しちゃってるのだろうか?)

※コード例が簡素なサンプルすぎるせいで書き捨てコードの話に見えてしまうかもしれませんが,ふつーに「(仕事でも趣味でもいいですが)実用するコード」での話だと思ってください.

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

#4

tmp

総合スコア338

投稿2025/07/30 08:57

普段CでC++使っていません。class X;は、なに!?
classのメソッドの順番は関係ないが
関数だとFunc.hがないとFunc.cppの関数Func1の中であとで出現するFunc2呼びにくい。(プロトタイプ宣言無しの呼び出し)

今は不要でも今後の修正時に、関数の書く順序を考えたり、入れ替えたりとかが、不要になるからとか

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

#5

hiroki-o

総合スコア1528

投稿2025/07/30 14:46

以下の3環境で確認しましたが、Func.cppから#include "Func.h"は不要なのですね。
あれ? 今日から私もC++初心者?

OSコンパイラー
Windows 11Visual Studio 2022
FreeBSD 14.3g++ 16.0.0
FreeBSD 14.3clang++ 21.0.0

いずれも、標準C++23で確認。

X.h

#pragma once #include <iostream> class X { public: X(){}; void test() const { std::cout << "class X" << std::endl; }; };

Func.h

#pragma once class X; int Func1(int, double); int Func2(const X&);

Func.cpp

#include <iostream> #include "X.h" int Func1(int x, double y) { std::cout << "Func1" << std::endl; return 0; } int Func2(const X &x) { x.test(); return 0; }

test.cpp

#include "Func.h" #include "X.h" int main() { Func1(1, 1.0); X x; Func2(x); return 0; }

出力

Func1 class X

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

#6

thkana

総合スコア7739

投稿2025/07/30 15:26

オーバーロード不可能な形でシグネチャを書き損じた場合とかにコンパイルエラーが欲しい

ので、(自動書記でなく)意識して書いてます。実際にそういう間違いをするか...といわれるとどうだろう?あまりしないかも知れません。まぁ、それでも自分よりはコンパイラを信用するので。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

#7

fana

総合スコア12256

投稿2025/07/31 01:29

#4
将来誰かが Func.cpp に手を入れた時に「何かわからんけど突然コンパイル通らなくなった」みたいな余計な混乱が生じるかもしれないことを防止,みたいな意味合いでしょうか.
なるほど,参考になります.

#5
その反応……どうやらあなたも「なぜだか不明だけど include 書いてた派」ですね!?
さぁ悩みましょう.
「それでも俺は…… Func.cpp#include "Func.h" って書くんだ!」という道を貫くのか否か.

#6
関数オーバーロードが無い C であれば効く範囲もそれなりに広いでしょうけど,C++ だととても狭いですよね(戻り値の型が違うパターンだけかな).
それでもコンパイルエラーが出せるパターンがあるなら価値があるという感じですかね.

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

#8

HoshiMizu

総合スコア59

投稿2025/08/05 06:18

必要だと思って、特に気にせず書いてました。
#include "Func.h"

開発環境によっては自動的に追加されますね。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

#9

tetuhiroshi

総合スコア47

投稿2025/08/05 09:57

一つのヘッダ内に互いに関連し合う複数のクラスがある場合、ヘッダをインクルードすることで、実装ファイルで手書きで前方宣言を書かずに済む場合があるかもしれませんね。
けれど、クラス相互の循環参照をなくすいつものテクニックを使えば、ヘッダを分けて、「ヘッダをインクルードせず」前方宣言も最小限にできると思うので、ちょっと微妙でしょうか?
間違っていたらすみません。ご参考までに。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

#10

fana

総合スコア12256

投稿2025/08/05 10:55

編集2025/08/05 10:56

一つのヘッダ内に互いに関連し合う複数のクラスがある場合、ヘッダをインクルードすることで、実装ファイルで手書きで前方宣言を書かずに済む場合があるかもしれませんね。

実装ファイル(.cpp)で何らかのクラス群の宣言を必要とする(:定義は不要)という状態において,
その .cpp にそれらクラス群の宣言を書くのが 面倒/だるい/etc... というような話でしょうか.
(で,ヘッダにそれらの宣言があるならば,それを include しちゃうのが楽,っていう)

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

#11

tetuhiroshi

総合スコア47

投稿2025/08/05 14:20

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

自分の考えを整理したところ、以下のようなコードにまとまりました。

c++

1// header.h 2 3#ifndef HEADER_H 4#define HEADER_H 5 6// sleepyの内部実装がboyに依存しているとする。(両方ともpublicだから、ポリシーによってはありうる。) 7 8class A { 9public: 10 void sleepy(); 11 void boy(); 12}; 13 14#endif

c++

1// impl.cpp 2 3#include <iostream> 4 5// ヘッダをインクルードする場合、それだけでコンパイル可能。 6#if 0 7#include "header.h" 8#endif 9 10// ヘッダをインクルードしない場合、A::sleepy内でA::boyを参照するためには、ODR違反しないように、class Aの定義を一つのトークンも違えることなく再度書かなければならない。 11#if 0 12class A { 13public: 14 void sleepy(); 15 void boy(); 16}; 17#endif 18 19void A::sleepy() 20{ 21 boy(); 22} 23 24void A::boy() 25{ 26 std::cout << "do everything myself (without depending anything)" << std::endl; 27}

肝は、publicメンバ関数が、同じクラスのpublicメンバ関数に依存している、という部分です。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

#12

fana

総合スコア12256

投稿2025/08/07 04:14

編集2025/08/07 04:18

肝は、publicメンバ関数が、同じクラスのpublicメンバ関数に依存している、という部分です。

sleepy()boy() を必要とするか否かという話とは無関係に,まず

C++

1//impl.cpp 2void A::sleepy(){ /*...*/ }

っていうだけではコンパイル通らないんじゃないですかね.

この状況でヘッダをincludeすることは(本件のタイトルの文言とはちょうど真逆の)「必要なinclude」だと思います.

そこであえて「でも既存のヘッダファイルの存在を無視しつつ,そのヘッダファイル内の定義を手動で imp.cpp にコピーするのもいいよね!」という手段に出るというのは,さすがに普通ではないと思います.(そもそも,そんなことを毎度頑張ってやらなくても済むようにヘッダファイルとかいうのが用意されているのでは)

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

#13

tetuhiroshi

総合スコア47

投稿2025/08/07 07:05

おっしゃるとおりです。

フリー関数のプロトタイプを実装ファイルで(ヘッダ経由で)繰り返すか?と、
クラス定義のプロトタイプを繰り返すか、という問題は、あまり関連がありませんし、後者の場合は、ヘッダのインクルードは否応なく必要ですね。

意見交換のトピックが、普段自分も考えたりすることでとても興味を惹かれたので、勢いで文脈から外れた投稿をしてしまいました。

元の議論についてですが、私はこういう場合は、あくまでコンパイル可能な最小のコードを書きたいと思うことが多いです。実装ファイルのコンパイル自体は

「 .cpp と対になる(?)感じで書いたヘッダ内に .cpp の実装が必要とする記述が無い」

という理想的な(ただしまれな)状況においては、ヘッダをインクルードしなくてもできるので、コンパイラ(リンカを除く)に少しでもトークン解析の負担を書けたくないな、と。(メモリが1Kだった時代じゃないよ、とセルフツッコミはしますが。)

けれど、主さんと同じく、実際にプログラムを書くときは、手の赴くままにヘッダをインクルードしてしまいますね。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

#14

fana

総合スコア12256

投稿2025/08/07 07:51

勢いで文脈から外れた投稿をしてしまいました。

外れ具合(?)が小さすぎて全く問題ない感じです.
(むしろそういう勢いがもっとあってもいいのにとか思ってる派)

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

#15

PingHermit

総合スコア479

投稿2025/08/12 13:40

C++はよく知りませんが、
Cレベルでは、Func.cpp と Func.hの間に
齟齬がないかどうかの確認のため。
C++でも、リンク時の関数名見直すことになるよりは分かりやすいと思います。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

#16

fana

総合スコア12256

投稿2025/08/13 02:51

C++でも、リンク時の関数名見直すことになるよりは分かりやすいと思います。

これは具体的にどういうことでしょうか?
(includeの有無次第でリンクに関して何か作業が発生し得るという話でしょうか?)

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

この意見交換はまだ受付中です。

会員登録して回答してみよう

アカウントをお持ちの方は

関連した質問