きままにブログスマートフォン用の表示で見るきままにブログプログラミングを主とした私のメモ帳です。寂しいのでコメントください笑この広告は、90日以上更新していないブログに表示しています。2016-01-28ネタの蛇足的解説C++本記事はhttps://twitter.com/staryoshi/status/669763731610431488のたくさんの反響を記念して蛇足的な解説を並べたものです。C++に興味を持っていなかった人もこれを見て興味を持っていただけたら幸いです。実際にはこれらの表記で困ることはないのですが、こんなこともできてしまうという一種の例でもあります。このコラの目的は、同一の識別子を用いて関数呼び出しに見えるが実際の定義の仕方は異なるというものはどのくらいあるのか、というのが発端です。https://t.co/XiONjbFDYb"より。外見は同じだが中身が違う......C++だ、と思って作りました。目をこらしても文字に違いはありませんので文脈から読み取るしかありません。その前に今回、C++啓蒙のためのネタとして投稿したわけですが、どうもC++の魅力が伝えられなかったみたいで大変残念です。普通に書いていればマクロ名を小文字で書くこともなければ、ローカル変数に代入した変数名と関数名がかぶって混乱することもありません。知らなければラムダも関数オブジェクトもマクロもクラスも使わないで書くことだってできます。使わない機能は使わなければいいのです。C++は使いたい機能だけ使うことができますし、そうすれば自然にC言語に近くなってきます。便利なC言語のように使ってもいいと思いますし、多くの人がそうしているでしょう。今回のネタを通してC++が複雑奇怪だから触るのはやめよう、という思った方は他の最近の言語でも実は多くの機能を知らないのではないでしょうか。他の言語もだいたい似たようなことやそれ以上のことができますが、それを使わない選択も用意されています。修得するためには結局は1つ1つ丁寧に定義とその存在意義を把握して実際に使ってみるしかないのです。修得しなくても代替方法はいくらでも用意されています。してそんなものがあるかと言うことを改めて考えることでより表現力が広がり、(コーディングの)効率が上がるのではないかと思われます。perlやPHPもアレだし、Rubyも闇。Haskellは(初見で)訳分からないし、Rustは糞難しいし、どこに行っても闇しかないんです......。各コマのソースコード例1コマ目(関数呼び出し)C++関数とは、ある引数を取ってそれ(とまあいろいろな情報)を元にある結果を返すことのできる処理のまとまりです。引数には0個以上を指定します。inlineをつけても基本的には関数です。名前空間内定義}2コマ目(マクロ呼び出し)マクロとはC++のソースコード上にある識別子を別の識別子に置き換えてしまう黒魔法です。0個以上の引数を取る置換列により置換できます。マクロ呼び出し}3コマ目(メンバ関数呼び出し)C++にはクラスを定義できます。クラスには関数を持つことができ、通常はクラスを直接操作する関数です。メンバ関数と上記の関数とは扱いが異なります。staticをつけると上記の関数とほぼ同じ扱いになります。定義は同じく{}をつけるだけです。c;}4コマ目(関数ポインタやラムダ式の関数呼び出し)関数ポインタは関数のアドレスを別の変数Xに保持し、X経由でその関数を呼び出すものです。ラムダ式とは、端的にいえば関数を関数内でかけるようにして、さらに他の機能も加えて便利にしたものです。ラムダ式は関数オブジェクトと考えられますが実際にはクロージャ型という異なるものです。いうのも関数オブジェクトと定義してしまうとコンパイラが最適化できない場合があるためです。この2つは実は違う動作がなされるのですが、キャプチャしなければ同じ扱いなので一緒にしてしまいました。こちらの書き方も可能}キャプチャのないラムダ式も代入できます。キャプチャとは、ラムダ式の宣言されたスコープで見える変数を、ラムダ式内で利用することです。この場合、実質関数ポインタとなります。ラムダ式の実行}ちなみにキャプチャすると関数ポインタではなくクロージャ型です。以下の例ではラムダ式の外の変数xをキャプチャし、ラムダ式内で変更します。これ以上は本題から逸れるのでやめておきます。110}5コマ目(コンストラクタ呼び出し)コンストラクタはクラスを初期化する特別な関数です。コンストラクタはメンバ関数とは違ってクラス名と同じにしなければいけません。ちなみにスコープから抜けたりオブジェクトが破棄されたりするときに呼び出されるデストラクタは~をつけて明示的に呼び出せます。今回は~でも入っていたら分かってしまうので除外しましたが。コンストラクタの実行}7コマ目(関数呼び出し演算子)クラスには、そのクラスのインスタンスに直接()をつけて関数呼び出しのように振る舞える関数呼び出し演算子を定義できます。このようなクラスを関数オブジェクトと呼び、この発想を元に簡略記法のラムダ式が提案されました。C++では標準ライブラリやその他のインターフェースとして基本的な知識となります。0;}8コマ目(暗黙の型変換による呼び出し)たぶんC++を知っている人でも漫画内の短い文では推測が困難、あるいは説明不足故に想像がつかなかった人がいるかも知れません。C++では型は暗黙に(=知らないうちに)変換されることがあります。今回はこれを利用しました。0;}この暗黙の変換はやっかいな結果を生むこともあります。そこでこれを抑制するには、explicitをつけます。これを指定することにより、型変換が明示的あるいはコンストラクタに入れられるときのみに行われます。関数ポインタを返す}このexplicitをつけた変換演算子が呼び出されるのは、コンストラクタの直接初期化(=のない初期化)かあるいは明示的にキャストした場合に限られます。次の例ではクラスUがクラスCに変換するexplicit変換演算子を定義しています。クラスCへ暗黙の変換がされるのは1つだけです。コンストラクタで直接初期化する場合です。bool()はOKです。これはif分の中の条件は暗黙裏に変換されることが約束されているためです。蛇足ですが有用な使い方を示しておしまいにしておきます。{printf("奇数\n");}}*1:ここでいうインターフェースとは、Javaとかのインターフェースとは異なる使い方に注意して下さい。C++でもJavaでいうインターフェース相当のことはできますが、こちらは状態も持てます。operator()でなくとも一般の仮想関数として呼び出すこともできます。)はてなブログをはじめよう!staryoshiさんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。