こんにちは、イワムーです![]()
スギ花粉が終息し、ホッと一息ついていたのもつかの間、次はヒノキ花粉が猛威を奮っていますね![]()
以前に無花粉スギの開発に成功したというニュースを見て大喜びした覚えがありますが、無花粉ヒノキの開発も切に願ってやみません・・・。(もうあるかも
)
さて、今日は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()のようにメソッド名を変えるだけでも解決できます。
基底クラスと派生クラスで初期化処理を分けなければいけないような設計自体を見直すことも考えるべきかもしれません。
このあたりはケースバイケースですね![]()