質問

    

この質問にはすでに回答があります:

         

現在、C ++プロジェクトで使用されている古いCコードをリファクタリング/整頓しており、次のような関数を定期的に確認しています。

int f(void)

次のように書く傾向があります:

int f()

一貫性を改善するために、コードベース全体で(void)を()に置き換えない理由はありますか?具体的には、C ++の仮想メンバー関数が次のように記述されている場合:

virtual int f(void)

および派生クラスにはメンバー関数が含まれます:

<*>

これは有効なオーバーライドですか?さらに、ほぼ同一の署名に基づいたリンカーの問題が発生する可能性がありますか?

役に立ちましたか?

解決

Cでは、宣言 int f(void)は、パラメーターを受け取らないintを返す関数を意味します。宣言 int f()は、任意の数のパラメーターを取るintを返す関数を意味します。したがって、Cでパラメーターを受け取らない関数がある場合、前者が正しいプロトタイプです。

C ++では、 int f(void)は推奨されておらず、 int f()が推奨されます。これは、特にパラメーターを受け取らない関数を意味するためです。

他のヒント

Chrisの答えに追加するために、私の経験では、 int f()を使用することはCの悪い習慣です。正しく呼び出されます。

たとえば、次のコードは標準に準拠したCです:

#include <stdio.h>
void foo();
void bar(void) {
    foo();
}
void foo(int a) {
    printf("%d\n", a);
}

しかし、 a foo に渡されなかったため、未定義の動作になります。

C ++には、 foo の2つのバージョンがあります。1つは引数を取らないもの、もう1つは int を取るものです。したがって、 bar は未定義バージョンを呼び出してしまい、リンカーエラーが発生します( foo の定義が他にない場合)。

上記の答えは非常に正しいですが、これおよび他の多くの問題に関する優れた説明

ハイライト:

  

Cは関数を区別します   空のパラメーターリストで宣言されています   で宣言された関数   のみで構成されるパラメーターリスト   無効。前者はプロトタイプ化されていない   不特定の数を取る関数   後者は   プロトタイプ化された関数   引数。

     一方、

C ++は、   2つの区別   宣言とそれらの両方を考慮   noをとる関数を意味する   引数。

     

意図されているコードの場合   CまたはC ++としてコンパイルされた、最高の   この問題の解決策は常に   パラメータを取らない関数を宣言する   明示的なvoidプロトタイプを使用します。

     

空の関数プロトタイプは   C99の非推奨機能(それらは   C89にありました)。

編集:標準を見た後、おそらくfunc(void)構文はC ++で非推奨ではない ことに注意する価値がありますが、一般的にはCスタイルのイディオムと見なされます。私が出会ったほとんどのC ++プログラマーは、空のパラメーターリストを好むと思います。

編集2:C ++標準からの引用の追加、セクション8.3.5、パラグラフ2:

&quot; parameter-declaration-clauseが空の場合、関数は引数を取りません。パラメーターリスト(void)は、空のパラメーターリストと同等です。この特別な場合を除いて、voidはパラメーター型ではありません(ただし、void *などのvoidから派生した型は可能です)。&quot;

どちらの形式も廃止されるという言及はありません。標準の正しいセクションを示してくれたTribble氏の素晴らしいWebサイトに再び感謝します。

tl; dr: void を使用します。

C ++の下位互換性と、以下に示す曖昧さを考えると、最終的な答えを得るためにKnRとANSI Cに戻ることを断言します。

int getline(void);
int copy(void)
  

特殊なバージョンのgetlineおよびcopyには引数がないため、   ロジックは、ファイルの先頭にあるプロトタイプを示唆します    getline()および copy()である必要があります。しかし、との互換性のために   古いCプログラムでは、標準は古いスタイルとして空のリストを取ります   宣言、およびすべての引数リストのチェックをオフにします。言葉   明示的に空のリストには、 void を使用する必要があります。   [カーニガン&amp; Richie、Cプログラミング言語、1988年、Pgs 32-33]

and ..

  

空の引数リストの特別な意味は、許可することを目的としています   新しいコンパイラでコンパイルする古いCプログラム。しかし、それは悪い考えです   新しいプログラムで使用します。関数が引数を取る場合、宣言します   それら;引数を取らない場合は、void [ibid、Pg。 73]

編集:残りの部分をここで別の議論に分けます: 引数をとらない関数の宣言でvoidの使用を指定すると、The Most Vexing Parseに対処しますか?

C11 N1570標準ドラフト

void f()は非推奨、 void f(void)を推奨:

6.11.6関数宣言子

  

1   空の括弧を含む関数宣言子の使用(prototype-formatパラメーターではありません)   型宣言子)は廃止された機能です。

はじめに

  

2特定の機能は陳腐化しています。つまり、   この国際規格の将来の改訂での撤回。保持されているのは   広く使用されているが、新しい実装での使用(実装用)   機能)または新しいプログラム(言語[6.11]またはライブラリ機能[7.31]用)は推奨されません。

詳細な議論: https://stackoverflow.com/a/36292431/895245

C ++ 11 N3337標準ドラフト

void f(void) void f()も廃止されません。

void f(void)はCとの互換性のために存在します。 Annex C&quot; Compatibility&quot; C.1.7条項8:宣言子

  

8.3.5変更:C ++では、空のパラメーターリストで宣言された関数は引数を取りません。 Cでは、空の   パラメータリストは、関数の引数の数とタイプが不明であることを意味します。

void f()はCで非推奨になり、 void f(void)が推奨されるため、 void f(void)はas C ++が互換性を維持したい限り。

void f(void) void f()は、C ++では同じです。したがって、長い void f(void)は、CとC ++の両方でコンパイルするコードを書くことに関心がある場合にのみ意味があります。これはおそらく価値がありません。

詳細な議論: https://stackoverflow.com/a/36835303/895245

C ++では、 int f(void)は非推奨の宣言であり、 int f()と100%同等です。これは同じ署名です 。このコンテキストの void は、たとえば空白。また、これらはOne Definition Rule(オーバーロードしない)の対象となり、 Derived :: f(void) Base :: f()をオーバーライドします。

ただし、 f(const void)のようなものを混乱させないでください。その種の奇妙さの意味するコンセンサスはあまりありません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top