忍者ブログ

神戸電子専門学校ゲームソフト学科の生徒が運営するGESのブログです。

   

[PR]

×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

usingのススメ

どうも、忍者ブログの不便さに辟易としてきたまむです!

今回は、そろそろC++を本格的に扱いだしたのではないかと思われる、二年生の方向けの記事を書きます。

今回の題材は「using」です。


拍手[0回]




usingは、いくつかの役割を持っています。

まず最初に、有名な「namespaceの省略」から。
#include <iostream>
using namespace std;

int main() {
cout << "Hello, world!" << endl;
return 0;
}


実行結果

「cout」や「endl」の頭に付けていた煩わしいstdを滅ぼすことができました。
しかし、安易にusing namespaceを使用すると大変危険です。

以下のコードを見てみましょう。
#include <string>
using namespace std;

typedef char* string;

int main() {
string name = "Alice";
return 0;
}


実行結果

「std名前空間」には「string」という型が存在しています。
「std名前空間にあるstring」では長いので「std::string」と書くことにしましょう。
……そういえばusing namespace stdを使用しているので「std」は省けますね。じゃあ「string」と書きましょうか。

さて、名前空間のない所で「char*のエイリアス(別名)string」を定義しましょう。
これもまた「名前空間のない所にあるchar*のエイリアスstring」では長いので「string」と書くことにしましょう。

さて、この時点でどこがまずいのか分かりますね。
そう、「string」という名前が思いっきり被ってしまっているのです。
こういった現象を「名前の衝突」と呼びます。

namespaceは、名前の衝突を避ける為に必要なものなので、安易にusing namespaceを使用して省略しないでね、というお話でした。


usingのネガキャンみたいになってしまいましたが、今回の記事タイトルは「usingのススメ」です。
最初に「いくつかの役割を持っている」と記した通り、usingの使用方法はこれだけではありません。

次のコードを見てみましょう。
using string = const char *;
using wstring = const wchar_t *;

int main() {
string name = "Alice";
wstring wname = L"アリス";
return 0;
}

実行結果

今回の役割は「typedefの代替」です。
typedefでは、型名のエイリアスを定義できましたが、usingを使用しても同じことができます。
「ならtypedefでいいじゃん」との声が聞こえてきそうですが、usingを利用する一番の利点は、その記述方法にあります。

関数ポインタfunction(int, int)のエイリアス定義の例を見てみましょう。
typedef int (*Function)(int, int);
using Function = int (*)(int, int);

どちらも記法が違うだけですが、usingの方が「エイリアスとして定義している」ことや「どこまでが型名でどこまでがエイリアスなのか」が分かりやすく、可読性が高まるかと思われます。

また、usingとtypedefの決定的な違いは「templateが使用できる」という点です。
template<typename T>
typedef std::vector<T> Vec;

このコードはコンパイルが通りませんが、


template<typename T>
using Vec = std::vector<T>;

usingを使用した場合、コンパイルが通ります。
これを活用することで、二つ以上の型パラメータを求められるとき片方を固定するなど、様々なことができるようになります。

最後に、以下のコードをご覧ください。
#include <iostream>
namespace Hoge {
void f() { std::cout << "Hoge::f()" << std::endl; }
}

void f() { std::cout << "::f()" << std::endl; }

int main() {
using Hoge::f;
f();
return 0;
}

実行結果

これは、using namespaceと非常に似た使用方法です。
しかし、大きく違うのは「宣言済みである指定の名前のものを持ってきて、現在のスコープに取り込む、或いは同名のものを覆い隠す」という動作を行うことです。
指定した物だけを持ってくることができるので、名前の衝突が起こる可能性が低くなります。
活用方法はあんまり思いつきませんが、覚えておいて損はしないでしょう。

長々と書いてきましたが、私が伝えたいことは「typedefよりusingを使おう」ということだけです。

ここまで読んで下さり、ありがとうございました!

はてな記法使いたい。
PR

COMMENT

NAME
TITLE
MAIL(非公開)
URL
EMOJI
Vodafone絵文字 i-mode絵文字 Ezweb絵文字
COMMENT
PASS(コメント編集に必須です)
SECRET
管理人のみ閲覧できます

ブログ内検索

最新コメント

[01/29 人面犬]
[10/01 8ch]
[09/12 uncle]
[09/10 某卒業生]
[06/07 uncle]

カレンダー

12 2020/01 02
S M T W T F S
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

テスト

Copyright ©  -- GESブログ --  All Rights Reserved
Design by CriCri / Photo by Geralt / powered by NINJA TOOLS / 忍者ブログ / [PR]