MENU閉じる

LAB

C++プログラムTIPS

研究室プログラムTIPSC++2010.4.9

using

今日はC++プログラムの小ネタを紹介しようと思います。
継承とポリモーフィズムの話です。
(分からない方は詳しく解説された他のWebページがあるので、そちらを参照してください)

class CharacterBase {
public:
  CharacterBase(void){}
  ~CharacterBase(void){}

  //初期化処理
  virtual void init(const Vector& position, const Vector& direction);

private:
  // メンバ定義
};

class Player : public CharacterBase {
public:
   Player (void){}
   ~Player (void){}

   //初期化処理
   void init(const Vector& position, const Vector& direction, const Vector3& scale);

private:
   // メンバ定義
};

上記例では、ポリモーフィズムの概念上、コンパイラは警告を出します。
警告が出る・出ないはコンパイラ、またコンパイラの警告レベルに依存します

initという名前のメソッドは基底クラスの仮想関数になっています。
今回のケースでは、派生クラスで同名のメソッドを宣言しているため、コンパイラ側からは「基底の仮想関数をオーバーライドするつもりで、引数を間違えたのではないか?」と見えてしまいます。
ですが、コーダーの意図としては「基底側と同様に機能としては初期化処理なのでinit()という名前のメソッドにしているが、引数や戻り値の異なる、基底側のinit()とは別のメソッドとして定義した」わけなので、コンパイラにその意図を知らせてあげればよいわけです。

class Player : public CharacterBase {
public:
   Player (void){}
   ~Player (void){}

   //初期化処理
   using CharacterBase::init; // ※この宣言に注目!!
   void init(const Vector& position, const Vector& direction, const Vector3& scale);

private:
   // メンバ定義
};

ここで using の登場です!!
このように基底クラスの同名メソッドをusing宣言しておくことで、警告を回避できるわけです。
using は名前空間を使用する際によく用いられる機能ですが、上記ケースでの利用はあまり知られていない(?)かと思ったので、紹介させていただきました。
何かのお役に立てばと思います!

補足:
上記例では、コンパイラの警告を除外することでも回避できます。
もちろん init()でなく、initPlayer()のようにメソッド名を変えるだけでも解決できます。
基底クラスと派生クラスで初期化処理を分けなければいけないような設計自体を見直すことも考えるべきかもしれません。
このあたりはケースバイケースですね。

RECRUIT

大阪・東京共にスタッフを募集しています。
特にキャリア採用のプログラマー・アーティストに興味がある方は下のボタンをクリックしてください

RECRUIT SITE