むりせず♪なまけず? ~ぷろくらすてぃねいたーの言い訳雑記~

よた ときどき .NET  by 刈歩 菜良 CTP

目次

ニュース

C# VB.NET掲示板
C#, VB.NET 掲示板

わんくま同盟
わんくま同盟

Vimエディタ日本語版

iPhone 無料アプリ

あわせて読みたい

日記カテゴリ

書庫

Blog 利用状況

コンストラクタイニシャライザ

長いコメント書くぐらいなら記事にしてしまえシリーズ #1

いんすぱいあーどばい「基本クラスのコンストラクタ

コンストラクタをオーバーライドしていっぱい作ったり、継承しているときに初期化の一部を基本クラスに依頼するときなどにコンストラクタイニシャライザを使います。
C#だとこんな感じ。

class A
{
    private int x;
    public A() : this(0) {} // ここですぐ下の引数を一つ取るコンストラクタに仕事丸投げ
    public A(int x)
    {
        this.x = x;
    }
    public virtual void output()
    {
        Console.WriteLine("x = " + x);
    }
}
class Aplus : A
{
    private int y;
    public Aplus() : this(0, 0) {} // ここですぐ下の引数を二つ取るコンストラクタに仕事丸投げ
    public Aplus(int x, int y) : base(x) // ここで派生クラスのコンストラクタを呼び出す
    {
        this.y = y;
    }
    public override void output()
    {
        base.output();
        Console.WriteLine("y = " + y);
    }
}


でも、C++だとコンストラクタイニシャライザにthisポインタが使えないので、自分自身の別のコンストラクタを呼び出すことができない。
使えるとするとこんな感じ。

class A
{
private:
    int x;
public:
    A():this(0){} // エラー!本当はここですぐ下の引数を一つ取るコンストラクタに仕事を投げたい!
    A(int x)
    {
        this->x = x;
    }
    virtual void output()
    {
        cout << "x = " << x << endl;
    }
};
class Aplus:public A
{
private:
    int y;
public:
    Aplus():this(0,0){}  // エラー!本当はここですぐ下の引数を二つ取るコンストラクタに仕事を投げたい!
    Aplus(int x, int y):A(x) // 基本クラスのコンストラクタなら呼び出せる。
    {
        this->y = y;
    }
    void output()
    {
        A::output();
        cout << "y = " << y << endl;
    }
};

なんでC++やと使えへんのかなぁ?
同じコードをあっちこっちに書くとメンテナンス性が落ちるがなぁ。
初期化用のprivateメソッド作ってそれをコンストラクタから呼び出すしかないんかな?
# と、疑問だけ投げかけて放置してみる。

投稿日時 : 2007年2月16日 14:27

Feedback

# re: コンストラクタイニシャライザ 2007/02/16 14:29 επιστημη

> 初期化用のprivateメソッド作ってそれをコンストラクタから呼び出すしかないんかな?

です。

# re: コンストラクタイニシャライザ 2007/02/16 14:32 シャノン

> です。

でも、それだと const メンバとか参照が初期化できんでなぁ。
そいつらの初期化は、結局、全部のコンストラクタに同じことコピペするしかないんかなぁ。

# re: コンストラクタイニシャライザ 2007/02/16 14:35 刈歩 菜良

επιさん、はやっ!
やっぱそうなんですねぇ。

でも、C#みたいなことがC++でもできたらよいなぁ。と、思うのですが、何かあえてそうしない理由なんてあるのかしらん?

と、思ってみたり...

# 未読フィード900突破
# 早く新しく入った方々にお礼詣り(゜o゜;)をしてフィードに追加しなくっちゃ。

# re: コンストラクタイニシャライザ 2007/02/16 14:36 刈歩 菜良

シャノンさんも、はやっ!

そうですよね、やっぱ力技チックな感じは否めないですよねぇ。

# re: コンストラクタイニシャライザ 2007/02/16 14:42 R・田中一郎

C++だとできないんですね。
どうしてなんでしょうね。

# re: コンストラクタイニシャライザ 2007/02/16 14:54 とっちゃん

なんかどっかで見た話題w

>どうしてなんでしょうね。
「現時点の」「仕様にない」から。
ってのが答ではないかとw

逆にC#でできるのは「仕様にある」からw

# re: コンストラクタイニシャライザ 2007/02/16 15:26 επιστημη

> それだと const メンバとか参照が初期化できんでなぁ。

ですです。
初期化できるのはコンストラクタの '{' 直前までですからねー。
それ以後は代入にしかならんし。

# re: コンストラクタイニシャライザ 2007/02/16 16:14 刈歩 菜良

> 「現時点の」「仕様にない」から。
あえてできないようにしてるのではないのですね。
ぢゃ、ぜひ次の仕様に...
(^O^)/

# だって、なんでもできちゃうってのがわたしのC++の印象なので、これができないとなんかC++っぽくない(超偏見)。

# re: コンストラクタイニシャライザ 2007/02/16 16:32 επιστημη

できちゃうと矛盾が生じる気が汁。

class Hoge {
 int value;
public:
 Hoge(int i) : value(i) {}
 Hoge() : this(0), value(0) {}

}

とか「書けてしまう」わけで、
そーなるとvalueを2度初期化することになります。
初期化子にthis(...)または 基底クラス(...)
だけが許されるなら別ですが、そーすると参照の
初期化ができなくなります。

# re: コンストラクタイニシャライザ 2007/02/16 17:11 刈歩 菜良

おぉ!
さすが紙。ぃゃ、神! するどいっ!

そっか、C#とちがって、そもそもメンバーイニシャライザとして使えるから(ってか、そっちがメイン用途?)話がややこしいんですよね。

上記の例だと単なるintだから上書きで初期化でええやんとも強引に考えれますけど、constやとそうは問屋がおろさなくなりますねぇ。

ん?まてよ。そもそもthisで飛ばすって時は往々にして仕事を丸投げしたいわけやから、thisで飛ばす時はそれ以外のイニシャライザー書けないとかってどうでっしゃろか?

# re: コンストラクタイニシャライザ 2007/02/16 17:26 επιστημη

> thisで飛ばす時はそれ以外のイニシャライザー書けないとかってどうでっしゃろか?

そーすると、初期化されないメンバとかができてしまいそぉ。

class Hoge {
 int value;
 const int cvalue;
private:
 Hoge(int n) : value(n) {}
public:
 Hoge() : this(0) {} // cvalueが初期化できひん

};

# re: コンストラクタイニシャライザ 2007/02/16 23:31 刈歩 菜良

それはHoge(int)君の責任でやってくれてんとだめやと思いますよ。

たとえば、

Hoge(int n):value(n), cvalue(n){}

てな感じでしょうか。

だって、そうしないと引数一個のコンストラクタが直接呼ばれたときも使えんてことになっちゃいますよね。

# re: コンストラクタイニシャライザ 2007/02/17 0:05 επιστημη

ですね。
…んーむ、「thisで飛ばす時はそれ以外のイニシャライザー書けない」って制約を課したとき、辻褄が合うようきちんとコンストラクタを定義できるか一抹の不安を覚えますです。
const/参照メンバを唯一一回/必ず一回初期化せにゃならんのよね。

# re: コンストラクタイニシャライザ 2008/03/03 8:09 初心者

C++の勉強をしていてたどりつきました。
Hoge(int n=0) :value(n) {}
ではだめなのでしょうか?

# re: コンストラクタイニシャライザ 2008/03/06 0:55 めたぼ なら

初心者さん
> Hoge(int n=0) :value(n) {}
> ではだめなのでしょうか?
コメントありがとうございます。

ここでの話題は「コンストラクタから自分自身のコンストラクタを呼ぶ方法がない。」というのが主題なので、「引数がなければ0を代わりに引数としたい。」というのが問題ではないのです。

たとえば、
Hoge(int a, int b)
{
  ・
  ・
  ・
}
というのがあって、
Hoge(AruClass x):this(x.a, x.b){}
ということがしたいという時、C++だと対応できないのです。

# re: コンストラクタイニシャライザ 2008/03/10 14:56 初心者

なるほど。そういうことですか。
わかりやすい具体例ありがとうございます。
納得しました。

# re: コンストラクタイニシャライザ 2008/03/11 10:49 めたぼ なら

初心者さん
> わかりやすい具体例ありがとうございます。
こちらこそ、不明確だった点をご指摘いただきありがとうございます。
後に参照される方にとっても、非常に良いご指摘だったと思います。

今後とも何かご不明な点がございましたら、遠慮なくご指摘頂けると助かります。
_(_^_)_

タイトル  
名前  
Url
コメント