68

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

int f(void)

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

int f()

一貫性を向上させるために、コードベース全体で (void) を () に置き換えない理由はありますか、それとも私が気付いていない 2 つの微妙な違いはありますか?

より具体的には、C++ の仮想メンバー関数が次のように記述されている場合:

virtual int f(void)

派生クラスにはメンバー関数が含まれます。

int f()

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

4

6 に答える 6

101

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

C++ では、特にパラメーターを取らない関数を意味するため、int f(void)非推奨であり、推奨されていると思います。int f()

于 2009-01-06T12:37:52.813 に答える
21

Chris's answerに追加するにint f()は、私の経験では、関数の宣言をその定義と比較するコンパイラの機能を失い、正しく呼び出されるようにするため、C での使用は悪い習慣です。

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

#include <stdio.h>

void foo();

void bar(void) {
    foo();
}

void foo(int a) {
    printf("%d\n", a);
}

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

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

于 2009-01-06T12:43:15.220 に答える
18

以前の回答は非常に正しいですが、これと他の多くの問題についての素晴らしい説明を提供しているので、DavidTribbleの優れたページにリンクしています。

ハイライト:

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

一方、C ++は、2つの宣言を区別せず、両方とも引数をとらない関数を意味すると見なします。

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

空の関数プロトタイプは、C99では非推奨の機能です(C89の場合と同様)。

func(void)構文はC ++で非推奨ではないことに注意する価値がありますが、一般的にはCスタイルのイディオムと見なされています。私が遭遇したほとんどのC++プログラマーは、空のパラメーターリストを好むと思います。

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

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

どちらの形式も非推奨になることは言及されていません。標準の正しいセクションを教えてくれたTribble氏のすばらしいWebサイトに改めて感謝します。

于 2009-02-28T03:25:20.840 に答える
2

C11 N1570 標準ドラフト

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

6.11.6 関数宣言子:

1 括弧が空の関数宣言子 (プロトタイプ形式のパラメーター型宣言子ではない) の使用は廃止された機能です。

はじめに:

2 特定の機能は廃止されています。つまり、この規格の将来の改訂で撤回される可能性があります。それらは広く使用されているため保持されていますが、新しい実装 (実装機能用) または新しいプログラム (言語 [6.11] またはライブラリ機能 [7.31] 用) での使用はお勧めできません。

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

C++11 N3337 標準ドラフト

非推奨void f(void)でもありません。void f()

void f(void)Cとの互換性のために存在します。付録 C「互換性」C.1.7 条項 8: 宣言子:

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

void f()C では非推奨であり、推奨されてvoid f(void)いるためvoid f(void)、C++ が互換性を維持したい限り存続します。

void f(void)void f()C++ でも同じです。したがって、void f(void)C と C++ の両方でコンパイルされるコードを作成することに関心がある場合にのみ、より長い時間は意味があり、その価値はほとんどありません。

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

于 2016-04-25T08:36:56.697 に答える
-1

C++ では、int f(void)実際には非推奨の宣言であり、100% と同等int f()です。同じサインです。このvoidコンテキストでの は、空白などと同じくらい重要です。Derived::f(void)これは、それらが 1 つの定義規則 (オーバーロードしない) およびオーバーライドの対象であることも意味しますBase::f()

ただし、のようなものを台無しにしないでくださいf(const void)。そのような奇妙さが何を意味するのかについては、多くのコンセンサスがありません。

于 2009-01-06T12:50:58.060 に答える