C++クラスと継承完全制覇
感想
- 超、基礎的な話だと思うが、パーッと読める分量で良い
- C++ 固有のお作法みたいな書き方、理由とともに書かれている
- 他の言語は読めるけど C++ に不慣れなケースでコード読んでて「このお作法的な書き方なんだろ」と感じる人には良さそう
読んだ時期
- 2024-09-08 頃
〜〜〜 以下はメモ。雑多
クラス
-
クラス図とオブジェクト図の違い
- クラス図 : クラス
- オブジェクト図 : インスタンス
-
クラスの定義と実装を分ける
cpp
class Employee {
public:
int number;
...
void showData();
Employee(); // コンストラクタ
~Employee(); // デストラクタ
};
----
#include "Employee.h"
using namespace std;
Employee::Employee() {
...
}
Employee::~Employee() {
}
void Employee::showData() {
...
}
- 変数宣言
クラス名 変数名
cpp
Employee employee1; // コンストラクタに引数なしの場合
Employee employee1(111, "aaa"); // コンストラクタに引数ありの場合
-
オブジェクト指向の3本柱
- 継承 ( inheritance )
- カプセル化 ( encapsulation )
- 多態性 ( polymorphism )
-
多重定義
- C言語では同じ名前の関数を複数作れない
- C++では名前と引数で識別するので同じ名前で作れる
-
オーバーロードの2つのパターン
- 引数のデータ型が異なるもの
- 引数の数が異なるもの
-
アクセス指定子は3種類のみ
- public
- private ← デフォルト
- protected
-
コンストラクタ
- クラス名と同じ名前のメンバ関数
- 戻り値の方を指定しない
- 継承はされないが、自動的に呼び出される
- 親クラスが先
- 保持されてるクラスが先
-
デストラクタ
- 引数も戻り値もも持たない
- オーバーライドできない
- 継承はされないが、自動的に呼び出される
- 子クラスが先
- 保持してる クラスが先
-
引数渡しのときの動作 -> コピーコンストラクタ
cpp
Employee(const Employee &obj); // コピーコンストラクタ
- 代入時の動作 -> 代入演算子のオーバーロード
cpp
Employee &operator=(Employee &obj);
-
演算子のオーバーロードと
-
継承
- public 指定しないとメンバが限定されてしまう(省略すると private)
cpp
class Salesman : public Employee {
};
-
親/子クラスの呼び名
- 親クラス = 基本クラス = 基底クラス = ベースクラス = スーパークラス
- 子クラス = 派生クラス = サブクラス
-
汎化
- 複数クラスに共通するメンバを親クラスにまとめること
-
継承 ( is-a 関 連 )
- 親クラスから引き継ぐこと
-
集約 ( has-a 関連 )
- ほかクラスのオブジェクトをメンバに持つこと
-
イニシャライザとメンバイニシャライザ
cpp
NewClass::NewClass(int n, int m)
: BaseClass(m) // ← イニシャライザ。親クラスの どのコンストラクタを呼ぶか決める。これをイニシャライザという
, member1(m) // ← メンバイニシャライザ。コンストラクタでなくメンバ変数名を指定
{
...
}
- オーバーライドする関数(仮想関数) -> virtual をつける
cpp
class MyClass {
public:
virtual void func2(const char *2);
};
- 純粋仮想関数(=子クラスでの実装を)
cpp
class Figure {
public:
virtual void draw() = 0;
}
- 子クラスから親クラスのメンバ関数を呼ぶ
cpp
BaseClass::func2(s)
-
多態性
- 基本クラスのポインタに派生クラスのオブジェクトのポインタを代入できる
-
多重継承
cpp
class Child : public Father, public Mother {
};
-
変数の種類
- ローカル変数
- 関数内部で宣言された変数
- 宣言に行き当たったときに確保(作成)
- 関数を抜けるときに解放(破棄)
- グローバル変数
- 関数の外部で宣言された変数
- プログラムの起動時に確保(作成)
- プログラムの終了時に解放(破棄)
- static 変数(関数内部で定義)
- 関数が初めて呼び出されたときに確保(作成)
- プログラムに終了時に解放(破棄)
- static 変数 (クラスのメンバ変数として定義)
- グローバル変数なので、クラス定義の外で実体を宣言する必要がある
- それは1回しか呼ばれないため、インクルードファイルに書かないこと。
- グローバル変数なので、クラス定義の外で実体を宣言する必要がある
- ローカル変数
-
メモリの確保と解放
- new
- delete
-
メモリ領域のグループ
- コード領域 -> 命令が格納される
- データ領域 -> グローバル変数、static 変数 が格納される
- スタック領域 -> ローカル変数 が格納される(確保してあるメモリ領域上に、使われるたびに積まれていく)
- ヒープ領域 -> 動的オブジェクト(new 演算子で作成された変数)
-
フレンド関数
- 外から、すべてのメンバを利用できる関数
- メンバでないので継承されない
- 2つのクラスのオブジェクトを引数に持ってオブジェクトのメンバ変数どうしを比較するような使い方をする
- その場合は前方参照 (
class MyClass;
が必要 )
- その場合は前方参照 (
cpp
class MyClass {
public:
friend void show(MyClass *ptr);
}
void show(MyClass *ptr) { // メンバ変数ではないので、namespace 指定しない
...
}
- 演算子のオーバーロードとfriend
cpp
Point operator+(int rhs); // rhs が別の型のとき
- テンプレートクラス
- クラスをつくる人が関数のアルゴリズムだけを実装
- クラスを使う人がメンバ変数やメンバ関数の引数のデータ型を決める
- 同じ機能でデータ型だけが異なるメンバ変数とメンバ関数を持つクラスを複数作成する状況に遭遇したときに活用
cpp
template <class datatype> class TPoint {
public:
datatype x;
datatype y;
void showData();
}
template <class datatype> void TPoint<datatype>::showData() {
...
}
雑多メモ
- static 変数
- 「関数内の変数を static にしてポインタとして return 外部で参照する」という使い方をしていた
- よく使われる方法なのかもしれないが、危険そうに感じてしまう
- C言語では「自己参照構造体」を使ったサンプルが、「この言語をマスターした証」なのだそうな
英単語
- quadratic
- 二次の