C++ デフォルト引数はプロトタイプ宣言だけにする default argument given for parameter
スポンサーリンク
このドキュメントの内容は、以下の通りです。
はじめに
C++言語 は、精力的に新しい機能が実装され、GNU GCCやClangなどの新しいバージョンが次々とリリースされます。次々と新しいプログラミング言語が開発され、便利なスクリプト言語が次々と登場していますが、C言語やC++言語は、いまでも根強い人気があるように思います。組み込み系で使われていたり、やはり実行速度が速い、といったメリットがあるからなのではないか、と思っています。
GNUGCCの 古い g++(コンパイラ) でコンパイルするときは、問題にならなかったけど、いつの間にかエラーになってコンパイルできなくなってしまった、というお話です。
どういうわけか、古いコンパイラを使わないといけない環境に長くいた影響なのか、現代のGNU g++の環境にソースコードを持ってきて、コンパイルしようとしたらエラーが続出でびっくりしました。
とりあえず、コンパイルしてくれてもいいじゃない?とか思うのですが、そういうわけにもいかないので、いろいろ直すことになりました。
今回 g++ で問題になったのは、デフォルト引数とプロトタイプ宣言と関数の実装のエラーです。
使っているコンパイラでコンパイルができても、 新しいコンパイラが出たときに、そのソースコードがコンパイルできるとは限りません。また、コンパイラの世代が何代も変わっていると、原因になるエラーが多すぎて、どこから手を付けて良いのかわからなくなってしまう可能性もあります。新しいコンパイラをできるだけ、試したほうがよいのだと思います。
2020年に少し記事を更新しました。新しい g++ のエラーや clang++ でのエラーも掲載しましたので、参考にしてください。
この記事の後半で紹介しますが、clang だと以下のエラーになります。
error: redefinition of default argument
note: previous definition is here
デフォルト引数とは
そもそも C++ の デフォルト引数とはなんでしょうか?
デフォルト引数は、関数を呼び出すときに、引数が指定されなかったときに使われる値です。デフォルト引数を利用することで、プログラミングをするときに、引数を省略することができます。
サンプルコード
たとえば、このようなソースコードを書きます。ここで重要なのは、デフォルト引数です。
関数 func に id という整数の引数があります。デフォルトの値は 0 です。
#include <iostream> #include <cstdlib> using namespace std; void func ( int id = 0 ); void func ( int id = 0 ) { return; } int main (int argc, char *argv[]) { func ( ); exit (EXIT_SUCCESS); }
コンパイルするとデフォルト引数でエラーが出る
サンプルのプログラムをコンパイルしてみます。
% g++ -Wall default_arg.cc default_arg.cc: In function 'void func(int)': default_arg.cc:7: error: default argument given for parameter 1 of 'void func(i' default_arg.cc:5: error: after previous specification in 'void func(int)' 1で終了しました
英語のエラーが出てしまって、戸惑ってしまう方もおられるかもしれませんが、心配いりません。
g++コンパイラさんが親切にも
デフォルト引数が与えられているとか、
前に指定しているとか、ゴチャゴチャ言ってきます。
何が悪いのか?
C++のプログラムのプロトタイプ宣言部と関数宣言の両方で、デフォルト引数を設定しているのが問題でした。
具体的には、サンプルのプログラムのこの部分です。
void func ( int id = 0 ); void func ( int id = 0 ) { return; }
そもそもこのレベルのプログラムでプロトタイプ宣言しなくてもいいじゃない、というのはなしです。
ヘッダファイルに宣言して、ほかのプログラムから利用させるということにしておいてください。
プロトタイプ宣言は、関数のパラメータがどうなっているのか、コンパイラにおしえるものなので、こちらにデフォルト引数を指定します。
ライブラリとして提供する場合、ライブラリを利用するプログラムは、ヘッダファイルをインクルードして使います。
そのときに、デフォルト引数が何個あるのか、知らないとコンパイラが困ります。
デフォルト引数として宣言していないと、必ず、引数をセットしないといけなくなります。
というわけで、関数宣言部分からデフォルト引数を削除します。
void func ( int id = 0 ); void func ( int id ) { // ここの id = 0 を id だけにしました。 return; }
これでC++のプログラムの問題は、解決しました。
2020年の環境では
2020年のコンパイラでは、どのようなエラーになるのか、紹介します。また、GNU GCC以外に Clang が使われている環境もあると思うので、Clang のケースについても紹介します。
vim のプラグインが表示しているものだと思われるのですが、プロトタイプ宣言部では、以下のエラーメッセージが出ています。
note: previous specification in 'void func(int)' here
void func ( int id = 0 );
また、関数の実装部分では、以下のエラーが出ています。
default argument given for parameter 1 of ‘'void func(int)' [-fpermissive]
void func ( int id = 0 ) { return; }
実際に g++ のバージョン7.5.0 でコンパイルするとこのようになります。
薫 $ g++ --version g++ (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0 薫 $ g++ -Wall default-argument.cc default-argument.cc: In function 'void func(int): default-argument.cc:14:24: error: default argument given for parameter 1 of void func(int)' [-fpermissiv] void func ( int id = 0 ) { ^ default-argument.cc:12:6: note: previous specification in 'void func(int) here void func ( int id = 0 ); ^~~~ [2] 276 exit 1 g++ -Wall default-argument.cc
g++のバージョン8だと以下の通りです。エラーメッセージは、 GNU GCC 7.5 系と変わらないように見えますね。
薫 $ g++8 --version g++8 (FreeBSD Ports Collection) 8.2.0 Copyright (C) 2018 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 薫 $ g++8 default-argument.cc default-argument.cc:14:24: error: default argument given for parameter 1 of 'void func(int)' [-fpermissive] void func ( int id = 0 ) { ^ default-argument.cc:12:6: note: previous specification in 'void func(int)' here void func ( int id = 0 ); ^~~~
clang++ のバージョン 3.8.1 の場合と以下のエラーが出ます。
$ clang++38 default-argument.cc default-argument.cc:14:17: error: redefinition of default argument void func ( int id = 0 ) { ^ ~ default-argument.cc:12:17: note: previous definition is here void func ( int id = 0 ); ^ ~ 1 error generated.
まとめ
- C++のデフォルト引数の値は、ヘッダファイルの関数宣言部で行いましょう
- プログラムの実装部分の関数の引数には、デフォルト引数の値を指定しません
スポンサーリンク
スポンサーリンク
いつもシェア、ありがとうございます!
もっと情報を探しませんか?
関連記事
最近の記事
- パナソニック ジェットウォッシャードルツ EW-DJ61-Wのホースの修理
- LinuxセキュリティモジュールIntegrity Policy Enforcement
- アマゾンのEcho Show 5を買ったのでレビューします
- アマゾンのサイバーマンデーはAlexa Echo Show 5が安い
- Android スマートフォン OnePlus 7T と OnePlus 7の違い
- Android スマートフォン OnePlus 7 をAndroid10にアップデートしてみた
- クレジットカードのバーチャルカードの比較のまとめ
- 活動量計 Xiaomi Mi Band 4を買ってみたのでレビュー
- Android スマートフォン OnePlus 7 のレビュー
- AliExpressでスマートフォンを買い物してみた
- パソコンのホコリ対策 レンジフードフィルターと養生テープ
- 80PLUS GOLDのPC電源ユニットAntec NeoEco 750 Goldのレビュー
- イギリスの付加価値税 VAT は払い戻しを受けられる
- イギリスのロンドンでスーツケースなど荷物を預けられる場所は
- イギリスのロンドンで地下鉄やバスに乗るならオイスターカードを使おう
- イギリスのヒースロー空港からロンドン市内への行き方
- 航空便でほかの航空会社に乗り継ぎがある場合のオンラインチェックイン
- SFC会員がANA便ではなくベトナム航空のコードシェアを試して解ったこと
- ベトナムの入国審査でeチケットの掲示が必要だった話
- シアトルの交通ICカードはオルカカード(Orca)です
人気のページ
- Windows7 IME 辞書ツールで単語の登録に失敗しました
- C言語 popen()でコマンドを実行して出力を読み込む
- Windows7で休止状態にする方法
- CentOS MySQLの起動、停止、再起動
- loggerコマンドでsyslogにエラーを出力する方法
- パソコンパーツの買取をしてくれる店のまとめ
- Java Mapの使い方 get(),put(),remove(),size(),clear()
- 楽天のRポイントカードを作ってみた
- iPhone 5 から iPhone 6 に乗り換えたのでレビュー
- netstatコマンドのステータスの意味
スポンサーリンク
過去ログ
2020 : 01 02 03 04 05 06 07 08 09 10 11 122019 : 01 02 03 04 05 06 07 08 09 10 11 12
2018 : 01 02 03 04 05 06 07 08 09 10 11 12
2017 : 01 02 03 04 05 06 07 08 09 10 11 12
2016 : 01 02 03 04 05 06 07 08 09 10 11 12
2015 : 01 02 03 04 05 06 07 08 09 10 11 12
2014 : 01 02 03 04 05 06 07 08 09 10 11 12
2013 : 01 02 03 04 05 06 07 08 09 10 11 12
2012 : 01 02 03 04 05 06 07 08 09 10 11 12
2011 : 01 02 03 04 05 06 07 08 09 10 11 12
2010 : 01 02 03 04 05 06 07 08 09 10 11 12
2009 : 01 02 03 04 05 06 07 08 09 10 11 12
2008 : 01 02 03 04 05 06 07 08 09 10 11 12
2007 : 01 02 03 04 05 06 07 08 09 10 11 12
2006 : 01 02 03 04 05 06 07 08 09 10 11 12
2005 : 01 02 03 04 05 06 07 08 09 10 11 12
2004 : 01 02 03 04 05 06 07 08 09 10 11 12
2003 : 01 02 03 04 05 06 07 08 09 10 11 12