【C++】継承

## 継承(※超重要)
**用途 : 既存のクラス(`基底クラス`)を元に、新しいクラス(`派生クラス`)を定義**
`備考 : クラスの三大要素(カプセル化、継承、多態性)の1つ。`

主に継承を使っていい場合は以下の2つ
**Is-A の関係** : 動物(基底クラス) is 犬(派生クラス)
**Has-A の関係** : 犬(基底クラス) has 心臓(派生クラス)

```C++:Animal.h
#ifndef ANIMAL_H_INCLUDED
#define ANIMAL_H_INCLUDED

#include <iostream>

/// <summary>
/// 基底クラス
/// </summary>
class Animal
{
public:
	/// <summary>
	/// デフォルトコンストラクタ
	/// </summary>
	Animal()
	{
		countLick = 5;
		std::cout << "アニマルクラスのコンストラクタ呼び出し" << std::endl;
	}

	/// <summary>
	/// デストラクタ
	/// </summary>
	~Animal()
	{
		std::cout << "アニマルクラスのデストラクタ呼び出し" << std::endl;
	}

	void Lick(void)
	{
		std::cout << "動物が舐めてきた!!" << std::endl;
	}

	int countLick; // 舐めた回数
};

#endif // !ANIMAL_H_INCLUDED
```

```C++:Dog.h
#ifndef DOG_H_INCLUDED
#define DOG_H_INCLUDED

#include "Animal.h"
#include <format>

/// <summary>
/// 基底クラス
/// </summary>
class Dog
	: public Animal
{
public:
	/// <summary>
	/// デフォルトコンストラクタ
	/// </summary>
	Dog()
	{
		std::cout << "ドッグクラスのコンストラクタ呼び出し" << std::endl;
	}

	/// <summary>
	/// デストラクタ
	/// </summary>
	~Dog()
	{
		std::cout << "ドッグクラスのデストラクタ呼び出し" << std::endl;
	}

	void Lick(void)
	{
		std::cout << std::format("犬が{}回舐めてきた!!", countLick) << std::endl;
	}
};

#endif // !DOG_H_INCLUDED
```

```C++:example.cpp
#include "Dog.h"

int main(void)
{
	{
		// アニマルクラスのインスタンスを生成
		Animal animal;
		animal.Lick();
	}
	std::cout << std::endl;
	{
		// ドッグクラスのインスタンスを生成
		Dog dog;
		dog.Lick();
	}

	return 0;
}
```

### アクセス指定子
**public(公開継承)** : 派生クラスにそのまま継承
**private(非公開継承)** : 派生クラスへ全てが非公開で継承

C++の標準ライブラリを開発するような人以外は、publicしか使いません(笑)

### アップキャストとダウンキャスト(C++)
**アップキャスト** : 基底クラスのポインタに派生クラスを格納
**ダウンキャスト** : 派生クラスのポインタに基底クラスを格納
※ダウンキャストは**使用禁止**

```C++:example.cpp
#include "Dog.h"

int main(void)
{
	{
		// アニマルクラスのポインタに
		// アニマルクラスのインスタンスを生成
		Animal* animal = new Animal();
		animal->Lick();
		delete animal;
	}
	std::cout << std::endl;
	{
		// アニマルクラスのポインタに
		// ドッグクラスのインスタンスを生成
		Animal* dog = new Dog();
		dog->Lick();
		delete dog;
	}

	return 0;
}
```

ドッグクラスのデストラクタが呼ばれていない...

## 仮想関数
**用途 : 基底クラスの関数を、派生クラスで上書き(`オーバーライド`)することを可能にする**

```C++:Animal.h
#ifndef ANIMAL_H_INCLUDED
#define ANIMAL_H_INCLUDED

#include <iostream>

/// <summary>
/// 基底クラス
/// </summary>
class Animal
{
public:
	/// <summary>
	/// デフォルトコンストラクタ
	/// </summary>
	Animal()
	{
		countLick = 5;
		std::cout << "アニマルクラスのコンストラクタ呼び出し" << std::endl;
	}

	/// <summary>
	/// デストラクタ
	/// </summary>
	virtual ~Animal()
	{
		std::cout << "アニマルクラスのデストラクタ呼び出し" << std::endl;
	}

	virtual void Lick(void)
	{
		std::cout << "動物が舐めてきた!!" << std::endl;
	}

	int countLick; // 舐めた回数
};

#endif // !ANIMAL_H_INCLUDED
```

### オーバーライド
**オーバーライド**は、基底クラスの仮想関数を継承し、上書きしたことを明示的にする

```C++:Dog.h
#ifndef DOG_H_INCLUDED
#define DOG_H_INCLUDED

#include "Animal.h"
#include <format>

/// <summary>
/// 基底クラス
/// </summary>
class Dog
	: public Animal
{
public:
	/// <summary>
	/// デフォルトコンストラクタ
	/// </summary>
	Dog()
	{
		std::cout << "ドッグクラスのコンストラクタ呼び出し" << std::endl;
	}

	/// <summary>
	/// デストラクタ
	/// </summary>
	virtual ~Dog()
	{
		std::cout << "ドッグクラスのデストラクタ呼び出し" << std::endl;
	}

	virtual void Lick(void) override
	{
		std::cout << std::format("犬が{}回舐めてきた!!", countLick) << std::endl;
	}
};

#endif // !DOG_H_INCLUDED
```

### 純粋仮想関数
**用途 : 継承先で純粋仮想関数のオーバーライドを強制させる**
- 備考
実装がなく**プロトタイプ宣言のみ**
また、純粋仮想関数を実装したクラスは**抽象クラス**になる(=インスタンス化不可)

#### C++
```C++:Animal.h
#ifndef ANIMAL_H_INCLUDED
#define ANIMAL_H_INCLUDED

#include <iostream>

/// <summary>
/// 基底クラス
/// </summary>
class Animal
{
public:
	/// <summary>
	/// デフォルトコンストラクタ
	/// </summary>
	Animal()
	{
		countLick = 5;
		std::cout << "アニマルクラスのコンストラクタ呼び出し" << std::endl;
	}

	/// <summary>
	/// デストラクタ
	/// </summary>
	~Animal()
	{
		std::cout << "アニマルクラスのデストラクタ呼び出し" << std::endl;
	}

	// 純粋仮想関数
	virtual void Lick(void) = 0;

	int countLick; // 舐めた回数
};

#endif // !ANIMAL_H_INCLUDED
```

```C++:example.cpp
#include "Dog.h"

int main(void)
{
	// アニマルクラスのポインタに
	// ドッグクラスのインスタンスを生成
	Animal* dog = new Dog();
	dog->Lick();
	delete dog;

	return 0;
}
```

#### C#
```C#:Animal.cs
using System;

public abstract class Animal
{
    public int countLick; // 舐めた回数

    /// <summary>
	/// デフォルトコンストラクタ
	/// </summary>
	Animal()
	{
		countLick = 5;
		Console.WriteLine("アニマルクラスのコンストラクタ呼び出し\n");
	}

	/// <summary>
	/// デストラクタ
	/// </summary>
	~Animal()
	{
		Console.WriteLine("アニマルクラスのデストラクタ呼び出し");
	}

    public abstract void Lick();
}
```

## 多態性(※超重要)
**多態性**とは、同名のメンバ関数が、異なる状況下で異なる処理を行うこと。

`備考 : クラスの三大要素(カプセル化、継承、多態性)の1つ。`

```C++
#include <iostream>

class Animal
{
public:
	Animal() {}
	virtual ~Animal() {}

	virtual void Voice(void) = 0;
};

class Dog
	: public Animal
{
public:
	Dog() {}
	virtual ~Dog() {}

	virtual void Voice(void) override
	{
		std::cout << "ワンワン" << std::endl;
	}
};

class Cat
	: public Animal
{
public:
	Cat() {}
	virtual ~Cat() {}

	virtual void Voice(void) override
	{
		std::cout << "ニャーニャー" << std::endl;
	}
};

int main(void)
{
	{
		Animal* dog = new Dog();
		dog->Voice();
		delete dog;
	}
	std::cout << std::endl;
	{
		Animal* cat = new Cat();
		cat->Voice();
		delete cat;
	}

	return 0;
}
```