プログラムTIPS

DEMO PROGRAM ヘキサドライブでは様々な研究開発をしています。その一部を紹介。

using(2010年4月9日)

今日は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()のようにメソッド名を変えるだけでも解決できます。
基底クラスと派生クラスで初期化処理を分けなければいけないような設計自体を見直すことも考えるべきかもしれません。
このあたりはケースバイケースですね。

【免責事項】

本サイトが提供している情報に関しては、安全性等、いかなる保証もされません。 株式会社ヘキサドライブは、これらの情報をあなたが利用することによって生ずるいかなる損害に対しても一切責任を負いません。

【著作権】

本サイトが提供しているコンテンツについては、特に断りのある場合を除き、株式会社ヘキサドライブが著作権を有します。