funini.com 自由研究 C/C++ コンストラクタ

コンストラクタ

コンストラクタ

C++でのコンストラクタは、ちょっと特別な関数。例えばクラス内の変数を初期化するときに、
class A{
  int n;
public:
  A(void){
    n = 123;
    /* コンストラクタの処理 */
  }
};
と書く代わりに、
class A{
  int n;
public:
  A(void) : n(123) { /* コンストラクタの処理 */ }
};
と書くことが出来る。intのコンストラクタをA(void)が継承している、見れる。
プロトタイプを使って書くときは、この:以降の部分は実体(.cppのほう)に書く。すなわち、
/* in A.h */
class A{
  int n;
public:
  A(void);
};


/* in A.cc */
A:A(void) : n(123)  {
  /* コンストラクタの処理 */ 
}

となる。


intくらいであれば普通に代入した方がむしろ見やすいが、もっと大規模なクラス(stringとか)の場合は、コンストラクタを使って書いた方が実行速度も速いし、見やすい。

継承とコンストラクタ

C++では継承(extension)が使える。例えば、Aを継承したクラスBを作ることができる。 このとき、Bを作ったときにはまずAの引数無しのコンストラクタ(デフォルトコンストラクタ)が呼ばれ、そのあとBの然るべきコンストラクタが呼ばれる。
#include 

class A{ protected; public: A(void){ std::cout << "A!" << std::endl; }

A(int n){ std::cout << "A : " << n << std::endl; }

};

class B : A{ public: B(void) { cout << "B!" << endl; } };

int main(void){ B* b = new B();

}

実行結果

A!
B!

でもこれはちょっと省略した書き方で、明示的にコンストラクタを指定するのが本流。

class B : A{
public:
  B(void) : A() {
    cout << "B!" << endl;
  }
};

他のコンストラクタを呼ぶことも出来る。

class B : A{
public:
  B(void) : A(1) {
    cout << "B!" << endl;
  }
};

実行結果

A : 1
B!

下のようなコード書いてみた。

#include<iostream> class Hoge{//Hogeクラスの宣言 public: int foo; Hoge(int foo_){foo = foo_;} // コンストラクタ int print(void){std::cout << foo << '\n';} // print関数 };

class SuperHoge: public Hoge{// hogeを継承したSuperHogeクラスの宣言 public: SuperHoge(int foo_){foo = foo_ * foo_;}// コンストラクタ };

int main(){ SuperHoge sh(3); sh.print(); }

コンパイルすると、下のようなエラー。

test.cc: In method `SuperHoge::SuperHoge(int)':
test.cc:21: no matching function for call to `Hoge::Hoge ()'
test.cc:7: candidates are: Hoge::Hoge(int)
test.cc:15:                Hoge::Hoge(const Hoge &)

SuperHogeを作る時は、まずHogeのコンストラクタが呼ばれ、さらにSuperHogeが呼ばれるのだが、 この書き方だと、呼ばれるHogeのコンストラクタには、引数は与えられないらしい。 なので、Hogeクラスの方にHoge(void){}というコンストラクタを定義する必要がある。

class Hoge{//Hogeクラスの宣言
public:
  int foo;
  Hoge(void){}
  Hoge(int foo_){foo = foo_;} // コンストラクタ
  int print(void){std::cout << foo << '\n';} // print関数
};

(追記) あるいは、下のように書くと、ちゃんとどのコンストラクタを継承するか指定できる。

class SuperHoge: public Hoge{// hogeを継承したSuperHogeクラスの宣言
public:
  SuperHoge(int foo_) : Hoge(foo_) {foo = foo_ * foo_;}// コンストラクタ
};