55

コンパイラ: g++ 4.7.2

Ok。.hそのため、とファイルのデフォルト パラメータについて混乱してい.cppます。多くの場所 (このサイトを含む) で、デフォルトのパラメーターは .h ファイルにのみ追加でき、.cpp ファイルには追加できないことが言及されています。ただし、このコードはそれが間違っていることを証明しています:

test1.h

#pragma once

#include <iostream>
using namespace std;

class Class{
public:
    Class(int, int, int=1);
};

test1.cpp

#include "test1.h"

Class::Class(int a, int b=2, int c)
{
    cout<<a<<" "<<b<<" "<<c<<endl;
}

int main()
{
    Class a(1);
    return 0;
}

今、私がテストしたことによると、デフォルトのパラメータを.cppファイルに追加できます。ただし、次の制限があります。

  1. .cppとファイルに存在するデフォルトのパラメーター.hは重複してはなりません。つまりClass(a, b, c=1)(.h ファイル内) および Class::Class(a,b,c=2)(.cpp ファイル内) は無効です。

    既定のパラメーターが追加されると、その後に宣言されたすべての変数にも既定値が含まれている必要があるというのはよく知られた規則です。これをdefparaルールと呼びましょう。今、

  2. 関数宣言 (.hファイル) に記述されている変数は、defpara規則に従う必要があります。つまり、 Class(a, b=2, c)(.h ファイル内) は、.cpp ファイルで宣言されている内容に関係なく無効です。

  3. .h変数がデフォルト値を持っていると考える場合 (およびファイル内のデフォルト値の共通部分として.cpp)、defparaルールに従います。すなわちClass(a, b, c=1)(.h ファイル内) および Class::Class(a,b=2,c)(.cppファイル内) は有効です。ただし、Class(a, b, c=1)(.h ファイル内) とClass::Class(a=2,b,c)(.cppファイル内) は無効です。

だから....私は正しい、間違っている???

4

4 に答える 4

92

関数がヘッダー ファイルで宣言されている場合、既定値は常にヘッダー ファイルに格納する必要があります。

これは、コンパイラがあなたのクラスを使用するすべてのコンパイル ユニットに対してヘッダー ファイルを使用するためです [あなたが「いたずら」をしていて、必要な場所でヘッダー ファイルを使用しない場合を除きます]。

コンパイラは、関数 (この場合はコンストラクター) を呼び出すコードをコンパイルするときに既定の引数を追加するため、.cpp ファイルの既定値は問題になりません。

もちろん、この場合、ヘッダーファイルの「ユーザー」は 1 つだけであり、コンストラクターが呼び出される場所は 1 つだけです。しかし、.cpp ファイルにデフォルトを設定するのは一般的に間違っています (ローカル関数でない限り)。

デフォルトを「混合」すると、非常に「興味深い」バグが発生します。たとえば、.cpp にデフォルトがあり、headefile に別のデフォルトがある場合などです。本当に熟練している場合は、関数のさまざまな呼び出しに対してさまざまなデフォルトを生成するようにコンパイラーを取得することもできます。これは、コードが特定の値であるデフォルトに依存している場合、ほぼ確実にヘッドスクラッチにつながります。また、「見やすくするためだけに」ヘッダーから .cpp ファイルにデフォルトをコピーしようとしないでください。誰かがデフォルトを変更した場合、ほとんどの場合、両方の場所で変更されないか、さらに悪いことに、間違ったデフォルトを変更して、意図したとおりに動作しない可能性があります。

于 2013-02-15T19:50:19.303 に答える
36

これは、メイン関数もtest.cppファイル内にあるためにのみ機能するため、クラスの実装で指定されたデフォルトの引数が表示されます。mainのみを含む別のファイルに関数を配置するtest.hと、このコードはコンパイルされません。

別の見方をすれば、他のインクルード が含まれている場合test.h、コードが認識するのは で宣言されているものtest.hだけであるため、他の場所に置かれたデフォルトの引数は使用されません。

于 2013-02-15T19:48:41.437 に答える
10

.hvs..cppは赤いニシンです。規則は、デフォルトの引数を関数宣言と関数の定義で使用できるということです。同じ値であっても、デフォルトの引数を再定義することはできません。したがって、これは合法ではありません。

void f(int, int = 3);
void f(int, int = 3); // error: redefinition of default argument

ただし、後続の宣言でデフォルトの引数を追加できます。

void f(int, int = 3);
void f(int = 4, int = 3);
f(); // calls f(4, 3);

さらに、関数が呼び出される任意の時点で、その時点で見られたデフォルトの引数を使用できます。

void f(int, int =3);
f(1); // calls f(1, 3);
void f(int = 4, int = 3);
f(1); // calls f(1, 3);
f();  // calls f(4, 3);

元の例では、.hファイルは1つのデフォルト引数を定義し、そのヘッダーを使用するすべての変換ユニットはそのデフォルト引数を使用できます。

Class c3(1, 2, 3);
Class c2(1, 2);

さらに、.cppファイルは追加のデフォルト引数を定義しているため、その宣言の後に、コンストラクターを1つ、2つ、または3つの引数で呼び出すことができます。

Class c3(1, 2, 3);
class c2(1, 2);
class c1(1);
于 2013-02-15T19:58:26.673 に答える
3

C++でのファイル定義のデフォルトパラメータのようなものはありません-それは宣言にのみ存在します。

何が起こるかというと、コンパイラーは後者のパラメーターが欠落している関数を認識します。これらがデフォルトの場合、関数呼び出しにこれらのパラメーターがあるかのように、空白を埋めてオブジェクトコードを作成し、関数を呼び出すことができます。

PS:アイテム38 / Scott Myers / EffectiveC++-継承されたデフォルトのパラメーター値を再定義しないでください。

于 2013-02-15T19:55:43.430 に答える