C ++名前付きパラメーター。 役に立たない

ときどき、C ++で名前付きパラメーターが突然必要になることがあります。 少し前に記事があり、彼しばらく前にこの主題について書きました。 そして、これは驚くべきことです。私の記事の時点から、古いコードを一緒にドラッグすることなく、新しいプロジェクトに参加してきました。 つまり 問題を理解し、見通しを賞賛し...そしていつものように働き続けました! どうして? 怠azine? 慣性? 私はカットの下で答えをしようとします。



まず、例を考えてみましょう-特定の日、月、年の日付オブジェクトを返す関数を宣言します。



Date createDate(int day, int year, int month);
      
      





問題は明らかです。1か月後、どのような順序でパラメーターが選択されないのでしょうか。



 Date theDate = createDate(2, 3, 4);
      
      





あなたは推測します:「これは何ですか? 2004年3月の2番目、または2002年の4番目ですか?」 特に幸運で、チームが国際的な場合、開発者による機能の解釈は根本的に異なる可能性があります。 同じタイプがパラメータリストの行にあります...このような場合、通常は名前付きパラメータが必要ですが、C ++ではそうではありません。



多くのプログラマーは、あるプログラミング言語から別のプログラミング言語に切り替える必要があります。 同時に、何かは新しい言語のようで、何かはそうではありません...悪いものは時間とともに忘れられますが、良いものはあなたが今働いている環境に確実に移されるでしょう。 そこでは、同じObjective-Cで名前付きパラメーターが利用できます!



 + (UIColor *)colorWithRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha
      
      





はい、最初のパラメーターには名前はありませんが、多くの場合、その名前はメソッドの名前に含まれています。 もちろん、このソリューションは理想的ではありません(たとえば、colorWithBlueメソッドは存在せず、色の不正など)、名前付きパラメーターは言語レベルでサポートされています。 VBAでは、すべてがさらに優れています-すべてのパラメータに名前を付けることができます。それらのおかげで、多くの同様のメソッドを作成することはできませんが、1つだけを実行します。 たとえばDocument.PrintOutを見てください



しかし、C ++にはそのようなものはありません! 私はすぐに状況を修正し、図書館を探し、松葉杖と自転車を思いつきます。 そして、何かさえ発見され、成功するでしょう。 しかし、代わりに、すべてがうまくいった場合、名前付きパラメーターが追加されていない理由を考えるかもしれません。 非常に多くのパラダイムがサポートされていますが、ここにあります...



それとも追加されましたか? 呼ばれただけです。 たとえば、カスタムタイプ。 記事の主なアイデアを説明する時が来ました。 原始標準型は実際のシステムのインターフェースに場所を持ちません 。 そのようなタイプは、構築する必要のある単なるビルディングブロックであり、内部に住もうとするものではありません。



たとえば、 int型のオブジェクトは、特定の範囲にある符号付き整数です。 このタイプの説明は何ですか? その実装のみ。 たとえば、リンゴの数にすることはできません。 リンゴをマイナス10にすることはできないため、さらに悪いことに、 unsigned intもこのタスクに適していません。 一般に、リンゴはプラットフォーム上のデータ型の次元とは関係がないためです。 言語のプリミティブ型をモデルのオープンメソッドのパラメーターにバインドすることで、ミスを犯し、さまざまな松葉杖の助けを借りて「急いで」しようとします。 さらに、監視を隠したいという欲求では、言語が私たちを助けようとしているという単純な事実をしばしば無視します。



しかし、プリミティブ型の主な欠点は、コンパイラが論理エラーを検出する機会を失うことです。 たとえば、2つのパラメーター(姓と名)をとるメソッドがあります。 それらを標準の文字列型に減らすと、コンパイラーは2つのテキストのみを認識し、その置換から意味は変わりません。 その結果、1人の開発者が名前に最初のパラメーターを渡し、もう1人が姓に渡します。 両方とも技術的には正しいでしょう。 名前と姓に特別なタイプが存在する場合、エラーは最初に破棄されます。 実際のシステムでは、名前と姓が非常に重要なエンティティであるため、インターフェイスに個別に入力されるため、単純に文字列に減らすとエラーになります。 名前は、任意の文字列ではありません。 事前に設定されたセットから選択されたためだけの場合。 また、たとえば、数字は含まれていません(ただし、ここではわかりません)。



しかし、日付に戻ります。 日は決してunsigned intでも、unsigned charでも、 std :: stringでもありません。 日は...日! 日付が存在するモデルを構築している場合、日を表す特別なタイプを作成することは理にかなっています。 カスタムデータ型は、C ++にすべての力と表現力を与えるものです。 その後、松葉杖は不要になります。 日を表すクラスを紹介します



 class Day { explicit Day (unsigned char day); //... private: unsigned char mValue; };
      
      





このようなもの。 当然、メモリ内の値の物理的表現には、プリミティブ型を使用します。 しかし、これはもはやインターフェースの一部ではありません。 すぐにこのフィールドの内容を完全に制御できるようになり、考えられる多くのエラーを排除します。 はい、完全な日付を知ることなく、正確な制限を確立することはできませんが、少なくとも間隔1..31に該当するかどうかのチェックはすでに手配できます。 最も重要なこと:プリミティブ型を初期化するための明示的なコンストラクターで月と年に特別なデータ型を実装することにより、言語で直接サポートされる名前付きパラメーターを取得します。 関数は次のように呼び出せるようになりました



 Date theDate = createDate(Day(2), Month(3), Year(4));
      
      





ロータリーや追加のライブラリはありません。 はい、そのようなアプローチではパラメーターを交換することはできませんが、これはそれほど重要ではありません。 名前付きパラメーターの主な使命-関数を呼び出すときのエラーを排除し、コードの可読性を高める-が実行されます。



おまけとして、たとえば月を文字列形式でも設定したい場合に、柔軟性が向上します。 createDateのオーバーロードされたバージョンを実行する必要はありません(これは日付オブジェクトを作成する機能であり、 実際に月の形式が重要なことです)。 代わりに、月タイプの別の明示的なコンストラクターが単純に追加されます。



 class Month { explicit Month(unsigned char month); explicit Month(std::string month); //... private: unsigned char mValue; };
      
      





誰もが自分でやっていることです-createDateは日付を作成し、 Monthクラスは月の値の正確さを解釈および制御します。



 Date theDate = createDate(Day(2), Month("Jan"), Year(4));
      
      





すぐに異議を申し上げたいのですが、プリミティブ型ごとに独自のラッパー型を作成する場合、不要な型が多すぎないでしょうか? 見方は次のとおりです。 ラボをすぐに作成する必要がある学生の場合は、合格して忘れてください。そうです-余分なコードが多く、時間が無駄になります。 しかし、あなたが興味を持っている長く幸せな生活の中で実際のシステムについて話しているなら、インターフェイスで使用されるエンティティのカスタム型に名前を付けることは不必要ではありません。



しかし、カスタムタイプはどうでしょうか。 たとえば、メソッドが同じタイプの複数のオブジェクトを受け入れる場合の処理



 User user1, user2; //... someMethod(user1, user2);
      
      





それはすべてコンテキストに依存します。 すべてのオブジェクトが同等である場合、問題はありません。転送の順序から何も変わりません。 これを強調するために、配列または他のコンテナにパックされたオブジェクトのみを転送できます。 オブジェクトが同等ではない場合、たとえば、メソッドがuser2をオブジェクトuser1に送信する場合、オブジェクトのロールを反映する特別なタイプが非常に役立ちます。 実装されているシステムに応じて、(プリミティブ型の場合のように)ユーザーオブジェクトのラッパーにするか、Userから継承する特別なクラスを作成する方が簡単です。 言語を使用してuser1およびuser2のさまざまな役割を何らかの形で表現することが重要であり、コンパイラが混乱の可能性に関連するエラーをキャッチできるようにします。



どの結論を引き出すことができますか。 すべての言語の中で最高のものをつかみ、すでにC ++に苦しんでいる言語に入れるように努力する必要はありません。 プログラミング言語を変更するときに慣性を克服できることが重要です。 はい、Luaでは一度に複数の変数に値を割り当てることができます



x、y = getPosition()



アイデア自体は素晴らしいですが、C ++で必要です。 通常は必要ありません。 位置タイプを作成し、そのオブジェクトに値を割り当てる方が簡単です。 言語はツールであり、それ以上のものではありません。 また、ツールが類似していることもあるという事実から、最小限の詳細までそれらを等しく使用する必要があるということにはなりません。



All Articles