C++0xにおけるコンストラクターのデリゲートのメモ。
class X
{
public :
X()
{
// 共通の初期化処理
}
X( int value )
{
// 共通の初期化処理
// 引数を使った追加の処理
}
} ;
この例では、どちらのコンストラクターも、初期化処理は共通している。同じコードが重複するのは、バグの下である。こういう場合、C++03では、共通の処理をメンバー関数に移すことができる。
class X
{
private :
void init() ;
public :
X()
{
init() ;
}
X( int value )
{
init() ;
// 引数を使った追加の処理
}
} ;
しかし、この方法では、非staticデータメンバーをコンストラクター初期化子で初期化することはできない。それに、結局init関数を呼び出さなければならないことにはかわりない。
class X
{
private :
int member ;
void init() ;
public :
X()
: member(123) // 重複
{
init() ;
}
X( int value )
: member(123) // 重複
{
init() ;
// 引数を使った追加の処理
}
} ;
コンストラクターを、別のコンストラクターに渡すことができればいいのだが・・・
C++0xでは、コンストラクターのデリゲートが提供されている。以下のように使う。
class X
{
private :
int member ;
public :
X()
: member(123)
{
// 初期化処理
}
X( int value )
: X() // コンストラクターのデリゲート
{
// 引数を使った追加の処理
}
} ;
このとき、X::X(int)を、delegating constructorという。デリゲートするコンストラクターは、デリゲート先のコンストラクターを実行してから、コンストラクター本体の実行に移る。コンストラクターをデリゲートする際には、コンストラクター初期化子には、他のメンバーやクラス名を書くことはできない。
もちろん、デリゲートは何度でも行える。
class X
{
public :
X() : X( 1 ) { std::cout << 1 ; }
X( int a ) : X( a, 2 ) { std::cout << 2 ; }
X( int a, int b ) : X( a, b, 3 ) { std::cout << 3 ; }
X( int a, int b, int c ) { std::cout << 4 ; }
} ;
int main()
{
X x ;
}
この例では、デフォルトコンストラクターはX::X(int)にデリゲートし、さらに、X::X(int,int)にデリゲートし、さらにX::X(int,int,int)にデリゲートされる。出力は、4321となる。
コンストラクターは、直接的、間接的に、自分自身に対して、デリゲートすることはできない。
class X
{
public :
X() : X() { } // エラー、直接的な自分自身へのデリゲート
// エラー、間接的な自分自身へのデリゲート
X( int ) : X( 0.0 ) { }
X( double ) : X( 0 ) { }
} ;
残念ながら現時点で、コンストラクターのデリゲートを実装しているコンパイラーは存在しない。コンストラクターの継承と合わせて、是非とも欲しい機能だ。この機能がなくてはコーディングが困難な現実の問題があるというわけではないが、このような簡単な機能こそ、是非とも普及して欲しい。
No comments:
Post a Comment