LoginSignup
56
47

More than 5 years have passed since last update.

[メモ] 継承と仮想関数

Last updated at Posted at 2017-11-12

C++の自分用の備忘録.
久しぶりにC++を触る機会があったのでまとめました.

virtualなしの場合

基底クラス(Base1)型変数は実体(インスタンス)に関わらず基底クラス(Base1)の関数が呼び出される.

non_virtual.cpp
class Base1 {
  public:
  Base1(){}
    void func() { cout << "Base1" << endl; }
};

class Sub1 : public Base1 {
  public:
    Sub1(){}
    void func() { cout << "Sub1" << endl; }
};
Base1* b1 = new Base1();
Base1* b2 = new Sub1();
b1->func();
b2->func();

実行結果

Base1
Base1

virtualありの場合

基底クラス(Base2)型変数でも実体(インスタンス)によって呼び出されるクラスの関数が変化する

virtual.cpp
class Base2 {
  public:
    Base2(){}
    virtual void func() { cout << "Base2" << endl; }
};

class Sub2 : public Base2 {
  public:
    Sub2(){}
    void func() { cout << "Sub2" << endl; }
};
Base2* b1 = new Base2();
Base2* b2 = new Sub2();
b1->func();
b2->func();

実行結果

Base2
Sub2

final/override(C++11)

  • final
    • 誤った継承の防止(クラス)
    • 誤ったオーバーライドの防止(関数)
  • orverride
    • 仮想関数(virtual)指定忘れ防止
    • 引数の型・個数の異なる関数のオーバーライド防止
    • オーバーライドするなら明示するようにする(個人の感想)
final_override.cpp
class Base1 final {} // 継承禁止クラス

class Base2 {
  public:
    Base2(){}
    // 仮想デストラクタ
    // 派生クラスのデストラクタが呼び出させるために
    // virutalが必要
    ~Base2(){}

    virtual void func_final() final;
    virtual void func_virtual();
    void func_nonvirutal();
};

class Sub : public Base2 {
  public:
    Sub(){}
    virtual ~Sub(){}

    // void func_final(); // finalメンバ関数はオーバーライドできない
    void func_virtual() override; // オーバーライドできる
    // void func_virtual(int a) override; // 引数の不一致. オーバーライドできない
    // void func_nonvirtual() orverride; // 非仮想関数はオーバーライドできない
};

純粋仮想関数

実装を持たないプロトタイプだけの関数
純粋仮想関数を持つクラスを「抽象クラス」と呼び, インスタンスを生成することができない. また, 継承したクラスは必ず実装しなればならない.

pure.cpp
class Base {
  public:
    virtual void func(void) = 0;
};

class Sub {
  public:
    void func() override { cout << "Sub(Override)" << endl; }
};

インターフェース

抽象クラスでインターフェースを表現し, 派生クラスで実装する.

interface.cpp
class IAnimal {
  public :
    virtual ~IAnimal(){};
    virtual void cry(void) = 0;
};

class Dog : public IAnimal {
  public:
    Dog(){}
    ~Dog(){}
    void cry() override { cout << "わんわん" << endl; }
};

class Cat : public IAnimal {
  public:
    Cat(){}
    ~Cat(){}
    void cry() override { cout << "にゃん" << endl; }
};
IAnimal *dog = new Dog();
IAnimal *cat = new Cat();
dog->cry();
cat->cry();

実行結果

わんわん
にゃん
56
47
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
56
47