ページ 11

基底クラス : 派生クラス と定義したとき、派生クラスで引数付きコンストラクタを定義するとコンパイルが通らない

Posted: 2012年7月24日(火) 10:29
by norm
下のコードは、superクラスと、それを継承したsubクラスを定義してます。
superクラスで引数aのコンストラクタを定義(中身は適当です。)して、
subクラスでオーバーライドしています。

コード:

class super {
public:
	super(int a) { a=a; }
};

class sub : public super {
public:
	sub(int a) { a; }    //エラー箇所
};

int main() {
	sub s(1);
	return 0;
}
コンパイラしたとき、//エラー箇所で

>> error C2512: 'super' : クラス、構造体、共用体に既定のコンストラクターがありません。
と言われてしまいます。

subクラスを継承した孫クラスなども順々に作っていきたいのですが、
地道に
protected:
super(){ }
などを作って行かないといけないのでしょうか?
何かこれに対する対策は無いのでしょうか?

Re: 基底クラス : 派生クラス と定義したとき、派生クラスで引数付きコンストラクタを定義するとコンパイルが通らない

Posted: 2012年7月24日(火) 11:14
by YuO
派生クラスに引数付きコンストラクタがあるからでは無く,
基底クラスに引数付きコンストラクタしかなく,それを派生クラスで呼び出していないためにエラーになっています。

コード:

sub (int a) : super(a) { /* ... */ }
のように,基底クラスのコンストラクタを正しく呼び出せばエラーになりません。

Re: 基底クラス : 派生クラス と定義したとき、派生クラスで引数付きコンストラクタを定義するとコンパイルが通らない

Posted: 2012年7月24日(火) 11:44
by norm
回答ありがとうございます!
YuO さんが書きました:

コード:

sub (int a) : super(a) { /* ... */ }
この
: super(a)
とは、何でしょうか?

前に、同じ部分に

コード:

sub (int n) : num(n) { /* ... */ }
というのも見たことがあるのですが・・・
numは親クラスのメンバ変数(関数ではなく)だった気がします。

Re: 基底クラス : 派生クラス と定義したとき、派生クラスで引数付きコンストラクタを定義するとコンパイルが通らない

Posted: 2012年7月24日(火) 12:18
by softya(ソフト屋)
コンストラクタの初期化子リストですね。
メンバ変数やメンバのクラスの初期化などで使います。

Re: 基底クラス : 派生クラス と定義したとき、派生クラスで引数付きコンストラクタを定義するとコンパイルが通らない

Posted: 2012年7月24日(火) 12:20
by YuO
norm さんが書きました:この
: super(a)
とは、何でしょうか?
コンストラクタ初期化子です。
コンストラクタにおいて,自身の複文を実行する前に初期化を行うための構文です。
norm さんが書きました:前に、同じ部分に

コード:

sub (int n) : num(n) { /* ... */ }
というのも見たことがあるのですが・・・
コンストラクタ初期化子では,
  • 仮想基底クラス
  • 直接の基底クラス
  • そのクラスに定義された非静的メンバ変数
の初期化を行います。
なので,メンバ変数の初期化もおなじ場所に出てきます。
norm さんが書きました:numは親クラスのメンバ変数(関数ではなく)だった気がします。
親クラスのメンバ変数は初期化できません (それは親クラスの役割)。

Re: 基底クラス : 派生クラス と定義したとき、派生クラスで引数付きコンストラクタを定義するとコンパイルが通らない

Posted: 2012年7月24日(火) 21:03
by norm
なるほどっ、そんなこともできるんですねっ! 
ありがとうございました!

Re: 基底クラス : 派生クラス と定義したとき、派生クラスで引数付きコンストラクタを定義するとコンパイルが通らない

Posted: 2012年8月13日(月) 13:13
by Norm
自分用メモメモメモメ
YuO さんが書きました:
norm さんが書きました:この
: super(a)
とは、何でしょうか?
コンストラクタ初期化子です。
コンストラクタにおいて,自身の複文を実行する前に初期化を行うための構文です。
//==================
super は、関数名ではなく、基底クラス名
基底クラスが、

コード:

class Oya {
  public:
    int num;
    Oya(int a) { ... } }
なら、サブクラスでは

コード:

class Ko {
  public:
    Ko(int a, int n) Oya(a), num(n) { ... } } 
:
とかにする。