web-dev-qa-db-ja.com

C ++関数スタイルのキャストの目的は正確には何ですか?

「type(value)」スタイルのキャストについて話しています。私が読んだ本は、Cスタイルのキャスト、「(タイプ)値」と意味的に同等であり、避けるべきであるとだけ言って、すぐにそれらを通過します。古いスタイルのキャストと同じことを意味するのなら、なぜ彼らは言語に追加されたのですか?また、宣言には余分な括弧を含めることができるため、次のコードは次のとおりです。 "T x(T(y));"関数スタイルのキャストを使用しようとしている人が期待することをしません。 yをTにキャストしてxという名前のT変数を作成するのではなく、Tを受け入れてTを返すxという名前の関数を宣言します。

彼らは言語のデザインの間違いでしたか?

26

関数スタイルのキャストは、プリミティブ型とユーザー定義型に一貫性をもたらします。これは、テンプレートを定義するときに非常に役立ちます。たとえば、次の非常にばかげた例を見てください。

template<typename T, typename U>
T silly_cast(U const &u) {
  return T(u);
}

ぼくの silly_cast関数は、関数スタイルのキャストであるため、プリミティブ型で機能します。クラスTにUまたはUconst&をとる単一の引数コンストラクターがある限り、ユーザー定義型でも機能します。

template<typename T, typename U>
T silly_cast(U const &u) {
    return T(u);
}

class Foo {};
class Bar {
public:
    Bar(Foo const&) {};
};

int main() {
    long lg = 1L;
    Foo f;
    int v = silly_cast<int>(lg);
    Bar b = silly_cast<Bar>(f);
}
24
leedm777

それらの目的は、クラスのコンストラクターに複数の引数を渡すことができるようにすることです。

_T(a1, a2); // call 2-argument constructor
(T)(a1, a2); // would only pass a2.
_

_(T) expr_スタイルのキャストが複数の引数を渡すことができるメカニズムがないため、新しい形式の変換が必要でした。 _(T) expr_をT(expr)の縮退したケースとして定義するのは自然なことです。

ここで言う人の言うこととは反対に、_(T) expr_はT(expr)とまったく同じように機能するので、クラス型でも問題なく機能します。

括弧がすでに頻繁に(過剰に)使用されている言語では、関数スタイルのキャストを解析する方がやや簡単です。

彼らは間違いでしたか?おそらく-しかし、Cスタイルのキャストに完全に取って代わることができなかったため、Perlのような「それを行う方法は複数あります」というメカニズムをキャストに提供しました。明確で独特な現代のキャストで:

dynamic_cast<type>(value);
reinterpret_cast<type>(value);
static_cast<type>(value);
const_cast<type>(value);

cスタイルのキャストを使用する理由はなくなり、関数スタイルのキャストを使用する理由も少なくなりました。

7

Cスタイルのキャストは使用しないでください。

特にターゲットタイプがクラス名(またはクラステンプレートの特殊化)である場合は、関数スタイルのキャストを使用する必要があります。これらは、引数が1つの場合の見かけのコンストラクター呼び出しのパターンに適合します。

MyClass( expr );   // Creates temporary, initialized like MyClass obj( expr );
MyClass( e1, e2 ); // Similar, and no other way to write this.
int( expr );       // Function-style cast.
3
aschepler

AFAIK関数スタイルのキャストは、クラスの一時的な作成の通常の構文のネイティブタイプの拡張です。構文ClassName(parameters)を使用して式内に一時オブジェクトを作成できる限り、すべきでない理由はありません。ネイティブタイプではそれを行いません。 edit@ steveが言ったように、これはテンプレートで非常に便利であることに注意してください

C++の1パラメーターコンストラクターは、変換機能として何らかの形で「感じられる」ことが多いことに注意してください。たとえば、equalを使用して新しいオブジェクトを初期化できる構文(conversionコンストラクター)を参照してください。記号の後に値が続く

ClassName MyObject = 3;

これは実際には

ClassName MyObject(3);

そして(おそらく)ClassNameのone -int- parameterコンストラクターを呼び出します。

ちなみに、 ここ は関数スタイルのキャストについての素晴らしいページです。

1
Matteo Italia