出力用シフト演算子(<<)のオーバーロード
C++ の標準ライブラリでは cout などにシフト演算子(<<)を使って出力します。
std::cout << "Hello World!!" << std::endl;
これは iostream の上位クラスである ostream のシフト演算子(<<)のオーバーロードで実現されているのですが、これを自分で定義したクラス、構造体、列挙型などに対しても定義しておくと便利です。
これを定義しておくだけで、標準出力(cout), ファイル(ofstream), 文字列(stringstream)などにも自分で作ったクラス等を文字列として出力することが出来ます。
どうやるかというと、例えば点の構造体 Point があったとすると以下のように ostream クラスとシフト演算子(<<)の 2 項演算をオーバーロードします。
std::ostream &operator<<(std::ostream &out, const Point &tgt)
{
out << "(" << tgt.x << "," << tgt.y << ")";
return out;
}
この定義はクラス(構造体)定義の外で行うので、列挙型も定義できます。
ただし、クラスの場合は外なのでゲッターなどを用意しておく必要があります。
さらに以下のようなテンプレート関数を用意しておけば、簡単に文字列に変更できます。
template <typename T_t>
std::string to_str(const T_t &val)
{
std::stringstream ss;
ss << val;
return ss.str();
}
この関数は int 基本型を含めた ostream のシフト演算子(<<)をオーバーロードしているものであれば何でも文字列に変換できます。
to_str(5); // "5"
to_str(Point(2, 3)); // "(2, 3)"
ちなみに入力用のシフト演算子(>>)を使えば 値 → 文字列 変換の from_str() のような関数も作れます。ただし、入力用の場合は変換できなかった場合の例外処理も必要になってきます。
実は Boost ではこの to_str()、 from_str() のような関数をもっと一般的にした lexical_castというのが用意されているので、 Boost 使えばすぐ使えるようになります。
Qt の場合だとこのようなテンプレートを使った変換は残念ながら用意されていないのですが、 Qt で用意されているクラスはほとんど QDebug というデバッグ用の出力先への演算子がオーバーロードされているので、何も定義しなくてもダンプだけならできます。
qDebug() << QPoint(2, 3); // "QPoint(2, 3)"
VS のビルドをコマンドラインで実行する
コマンドラインでビルドできるとバッチファイルなどのスクリプトで実行できるようになりますし、 Emacs 上からビルドもできるようになります。 Emacs 上でコンパイルする設定は以前少し書きました。
http://yohshiy.blog.fc2.com/blog-entry-10.html
私は Un*x 系での開発の場合は、編集、ビルド、デバッグとすべて Emacs 上からやるのですが、 Windows の開発でも 編集、ビルドまで Emacs 上でできます。デバッグだけはコマンドライン上からできないので、おとなしく Visual Studio でやってます。
MSBuild
ビルドをコマンドライン上からやるには MSBuild というプログラムを使用します。これは .NET ランタイムと一緒に配布されているもので通常以下の場所にインストールされています。
c:/Windows/Microsoft.NET/Framework/vX.X
ここに PATH を通せば、 MSBuild で呼び出せます。
使用法は以下の形式です。
$ MSBuild [プロジェクトファイル]
*.vcxproj(VS2010)、 *.vcproj のようなプロジェクトファイルだけでなく、*.sln のソリューションファイルもビルドできます。省略した場合はカレントフォルダにあるものを探して実行します。
オプションを指定していない場合はデフォルトの構成のものがビルドされます。ビルドの構成を指定して実行するオプションは若干面倒です。たとえば Release 指定してビルドする場合は以下のように呼び出します。
$ MSBuild /p:Configuration=Release
http://www.atmarkit.co.jp/fdotnet/special/msbuild01/msbuild01_01.html
.NET 以前
VC++6.0 など .NET の前の場合には 以下のようにしてビルドできます。
$ MSDEV.dsw /MAKE "target"
http://q.hatena.ne.jp/1213016943
Qt の場合
Qt の場合には qmake というツールを使って、 Qt 用のプロジェクトファイル(*.proj)から、 Un*x 系では make ファイル、 Windows 上では VC 用のプロジェクトファイルを生成することができます。
Windows 上で VC 用プロジェクトファイルを生成するためには *.proj の TEMPLATE の設定で vcapp を指定する必要があります。ただクロスプラットホームで開発している場合、 vcapp とプロジェクトファイルに記述すると今度は Un*x 系でエラーとなるので以下のようにして qmake を実行する必要があります。
$ qmake -tp vc
Windows 上でこの -tp vc をつけずに qmake を実行するとどうなるかというと、nmake という VC 用のメイクファイルが生成されます。 MSBuild を使うよりも nmake の方がビルドが若干速いようなので、私は Qt を Windows 上でコンパイルする場合 nmake を使っています。
ただし、この nmake は VS のスタートメニューの [Visual Studio 20XX コマンドライン] というところから実行すると上手くいくのですが、それ以外から実行しようとすると環境変数が設定されていないため、エラーとなります。
そこで、 Emacs などからビルドしたい場合には以下の環境変数を設定しておく必要があります。
- PATH
- INCLUDE
- LIB
- LIBPATH
設定する環境変数の値は以下のファイルなどを参考にして設定してください。
(VSのインストールフォルダー)\Common7\Tools\vsvar32.bat
C++ のキャスト
C++ には 4 つのキャストがあります。
名称 | 説明 | 使用 |
---|---|---|
dynamic_cast | 基本クラスから派生クラスへのキャスト | 使用するべきではない |
const_cast | const を外すキャスト | 使用するべきではない |
static_cast | double から int など暗黙の変換のあるキャスト | 使用可 |
reinterpret_cast | double * から long long などの無理やりキャスト | なるべく使用しない |
個人的には、 C++ のキャストは書くのがめんどくさいし、 static_cast 以外はあまり使うべきではないのに static_cast は C のキャストだしってことで、 C 形式のキャストでいいんじゃねって思っています。
ただし、コーディング規約で決まっている場合などがあって使わないといけない場合とかもあると思います。
そこで、使い方を考えてみます。
書き方
C 形式のキャストの場合は対象に括弧を付ける必要はないのですが、 C++ 形式の場合は必ず付ける必要があります。ival = (int)dval; /* C */ ival = static_cast<int>(dval); // C++C++ のキャストは形式としては言語の機能というよりも templete 関数の一種のような見た目になってます。めんどくさいのですが、 Boost の lexical_cast のようにキャストっぽい関数をつくって形式を合わせることができるという利点もあります。
コードの見え方とコードの質
C に比べ、 C++ のキャストでは確かに書くのがめんどくさいなりましたが、あまりやるべきではないことはめんどくさくするのがいいという考え方もあります。例えば Ruby ではグローバル変数やクラス変数には必ず $, @@ を付ける必要があります。こういったものは沢山使っているとコードが汚く見えます。 グローバル変数などを大量に使うことはコードの質としてもダメです。
コードの質の悪いものは汚く見えるので、綺麗に見えるようにコードを書きます。 そうすれば、自動的にコードの質も上がってきます。
C++ でのキャストの使用
C++ のキャストも、 C++ の型安全性を無理やり壊すので、よくないものだと言われています。(『 Effective C++ 』)めんどくさいものは使いたがらなくなりますし、 C++ のキャストの汚さやめんどくささはいいことかも知れません。
もちろん、 めんどくさいから C 形式のキャストを使うということになるとだめなので、コーディング規約などで使用を強制しておく必要があります。
最初に言っていたことと違うことになってますが、一概にキャストはダメという訳ではないので、次回からこのキャストについて詳しく考えていきたいと思います。
![]() | Effective C++ 原著第 3 版 (ADDISON-WESLEY PROFESSIONAL COMPUTING SERIES) (2006/04/29) スコット・メイヤーズ 商品詳細を見る |
![]() | Boost C++ Libraries プログラミング (2007/07) 稲葉 一浩 商品詳細を見る |
![]() | オブジェクト指向スクリプト言語 Ruby (ASCII SOFTWARE SCIENCE Language) (1999/10) まつもと ゆきひろ、石塚 圭樹 他 商品詳細を見る |