【C++】 基本型・クラス間の型変換を定義するには?

  • ????????????????????

c++ では static_cast<double>(int) とかやると型を変換できますが、それを自分で定義したクラスに対して行う方法について書いてみます。
コンストラクタを使ってやる方法もありますが、この方法だと int, double などの基本型(組み込み型)には使えません。たとえばあるクラス X を int 型にキャストしたい場合などですね。

X::operator int() を定義する

こういうときは次のような方法が有効です。

struct X {
  operator int(){ /* 変換のためのコード */}
};

このような operator T を定義しておくと、

X x;
int y=x;
int z=static_cast<int>(x);

というような書き方ができるようになります。

サンプル

上で書いてあることとほとんど同じですが、コンパイルできるコードを一通り書いておきます。
さまざまな型から Hoge クラスにキャストしたり、また、Hoge クラスから別の型へのキャストをするようなサンプルになっています。

#include &lt;iostream&gt;
#define castmsg(from, to) std::cout << "Cast from "#from" to "#to << std::endl;
struct Fuga {
  int fuga;
};
struct Hoge {
  int hoge;
  operator int(){   // Hoge -> int へのキャスト
    castmsg(Hoge,int);
    return hoge;
  }
  operator Fuga(){  // Hoge -> Fuga へのキャスト
    castmsg(Hoge,Fuga);
    Fuga f;
    f.fuga = hoge;
    return f;
  }
  Hoge(int h){      //  int -> Hoge へのキャスト
    castmsg(int,Hoge);
    hoge=h;
  }
  Hoge() : hoge(0) { }  // デフォルトコンストラクタ
};

int main(){
  Hoge hoge;
  hoge.hoge = 1;
  std::cout << "=== Type cast test (by static_cast) ===" << std::endl;
  /* Hoge -> int */
  int h = static_cast<int>(hoge);
  /* Hoge -> Fuga */
  Fuga fuga = static_cast<Fuga>(hoge);
  /* int -> Hoge */
  Hoge hogera = static_cast<Hoge>(4);
  std::cout << "Hoge->int  : " << h << std::endl;
  std::cout << "Hoge->Fuga : " << fuga.fuga << std::endl;
  std::cout << "int->Hoge  : " << hogera.hoge << std::endl;
  std::cout << "=== Type cast test (implicit) ===" << std::endl;
  /* Hoge -> Fuga */
  fuga = hoge;
  /* int -> Hoge */
  hogera = 6;
  std::cout << "hogera: " << hogera << std::endl;    // ここでも暗黙の Hoge->int が使われる
  //std::cout << fuga << std::endl;    // これはエラー!(Fuga->int は存在しない)
  std::cout << "fuga.fuga: " << fuga.fuga << std::endl;
}

/* 出力 */
/*
=== Type cast test (by static_cast) ===
Cast from Hoge to int
Cast from Hoge to Fuga
Cast from int to Hoge
Hoge->int  : 1
Hoge->Fuga : 1
int->Hoge  : 4
=== Type cast test (implicit) ===
Cast from Hoge to Fuga
Cast from int to Hoge
hogera: Cast from Hoge to int
6
fuga.fuga: 1
*/

暗黙の型変換を抑制する

上の例で言うと、ユーザー定義クラスの Hoge に int が = 演算子を使って代入できるようになっていますが、場合によってはこの挙動は危険だ、という場合もあるでしょう。そんなときはコンストラクタ Hoge(int) の前に explict 修飾子をつけましょう。
これをつけることで

Hoge x=1;

のようなコードをコンパイル時エラーにすることができるようになります。

はてなブックマーク - 【C++】 基本型・クラス間の型変換を定義するには?
Pocket