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
You can use some HTML elements, such as <b>, <i>, <a>, also, some characters need to be entity referenced such as <, > and & Your comment may need to be confirmed by blog author. Your comment will be published under GFDL 1.3 or later license with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.