閉じる

【C++】クラス入門:定義から使い方まで徹底解説

C++で本格的なプログラムを書き始めると、必ず登場するのがクラスです。

クラスはデータと処理をひとまとめにできる仕組みで、オブジェクト指向プログラミングの中心的な概念です。

本記事では、クラスの基本構造からコンストラクタ、メンバ関数、アクセス指定子、さらに少し応用的な使い方までを、サンプルコードと図解を用いながら丁寧に解説します。

C++のクラスとは何か

クラスの役割とイメージ

クラスとは、「データ」と「そのデータを扱う処理」を1つにまとめた設計図のようなものです。

C言語では構造体でデータだけをまとめていましたが、クラスではそれに加えて関数も一緒に持たせることができます。

たとえばゲームのプレイヤーを表すとき、次のような情報と処理をまとめて持てると便利です。

  • プレイヤー名やHPなどのデータ
  • ダメージを受ける、回復する、状態を表示するなどの処理

この「プレイヤーの設計図」がクラスであり、その設計図から実体として作られるものがオブジェクトです。

クラスは1つでも、そこから何体分ものプレイヤーオブジェクトを生成できます。

クラスの基本構造

クラス定義の書き方

C++でクラスを定義する基本形は次のようになります。

C++
// クラスの基本的な書き方
class クラス名 {
    // アクセス指定子: public, private, protected など
public:
    // 外からも使えるメンバ(変数・関数)

private:
    // クラスの内部からのみ使えるメンバ
};

クラス定義では、最後の;を忘れやすいので注意が必要です。

クラスは通常、関数の外(グローバルな位置)に書きます。

最もシンプルなクラス例

それでは、位置情報だけを持つシンプルなクラスを定義してみます。

C++
#include <iostream>
using namespace std;

// 2次元座標を表すクラス
class Point {
public:
    int x; // x座標
    int y; // y座標
};

int main() {
    Point p;      // Pointクラスのオブジェクトを生成
    p.x = 10;     // メンバ変数xに代入
    p.y = 20;     // メンバ変数yに代入

    cout << "x = " << p.x << ", y = " << p.y << endl;

    return 0;
}
実行結果
x = 10, y = 20

この例では、クラス定義オブジェクトの生成、そして.演算子によるメンバ変数へのアクセスという、クラスの最初の一歩を確認できます。

メンバ変数とメンバ関数

データと処理をまとめる

クラスの中には、主に次の2種類の要素を定義します。

  • メンバ変数(フィールド) … クラスが持つデータ
  • メンバ関数(メソッド) … そのデータを扱う関数

次の例で、両方をまとめて確認してみます。

C++
#include <iostream>
#include <string>
using namespace std;

// プレイヤーを表すクラス
class Player {
public:
    // メンバ変数
    string name; // プレイヤー名
    int hp;      // 体力
    int level;   // レベル

    // メンバ関数: ステータスを表示する
    void showStatus() {
        cout << "名前: " << name
             << ", HP: " << hp
             << ", レベル: " << level << endl;
    }

    // メンバ関数: ダメージを受ける
    void damage(int amount) {
        hp -= amount;
        if (hp < 0) {
            hp = 0;
        }
    }
};

int main() {
    Player p;           // Playerオブジェクトの生成

    // メンバ変数に値を設定
    p.name = "Alice";
    p.hp = 100;
    p.level = 5;

    p.showStatus();     // メンバ関数の呼び出し

    p.damage(30);       // 30ダメージを受ける
    p.showStatus();     // もう一度表示

    return 0;
}
実行結果
名前: Alice, HP: 100, レベル: 5
名前: Alice, HP: 70, レベル: 5

メンバ関数の中からは、同じクラスのメンバ変数namehpに、そのままアクセスできます。

クラスの「内側」では、自分が持っているデータを直接操作できるとイメージすると理解しやすいです。

コンストラクタとデストラクタ

コンストラクタで初期化する

クラスには、オブジェクト生成時に自動で呼ばれる特別な関数があります。

これをコンストラクタと呼びます。

初期値を設定したり、必要な準備を行ったりするのに使われます。

C++
#include <iostream>
#include <string>
using namespace std;

class Player {
public:
    string name;
    int hp;
    int level;

    // コンストラクタ: デフォルトの初期値を設定
    Player() {
        name = "NoName";
        hp = 100;
        level = 1;
    }

    // 引数つきコンストラクタ: 好きな値で初期化
    Player(const string& n, int h, int lv) {
        name = n;
        hp = h;
        level = lv;
    }

    void showStatus() {
        cout << "名前: " << name
             << ", HP: " << hp
             << ", レベル: " << level << endl;
    }
};

int main() {
    Player p1;                      // デフォルトコンストラクタ
    Player p2("Bob", 150, 10);      // 引数つきコンストラクタ

    p1.showStatus();
    p2.showStatus();

    return 0;
}
実行結果
名前: NoName, HP: 100, レベル: 1
名前: Bob, HP: 150, レベル: 10

コンストラクタはクラス名と同じ名前で書き、戻り値の型は記述しません。

複数定義しておき、引数の違いで使い分けることもできます。

デストラクタの役割

デストラクタは、オブジェクトが破棄されるときに自動で呼ばれる特別な関数です。

外部リソースの解放などに使います。

C++
#include <iostream>
using namespace std;

class Sample {
public:
    Sample() {
        cout << "コンストラクタ呼び出し" << endl;
    }

    // デストラクタ: ~クラス名 という名前で定義
    ~Sample() {
        cout << "デストラクタ呼び出し" << endl;
    }
};

int main() {
    {
        Sample s; // このブロック内で生存
    } // ブロックを抜けるとsが破棄され、デストラクタが呼ばれる

    return 0;
}
実行結果
コンストラクタ呼び出し
デストラクタ呼び出し

このように、デストラクタは主にメモリ以外のリソース(ファイル、ソケットなど)の後片付けで役立ちます。

アクセス指定子とカプセル化

publicとprivateの違い

クラスの重要な概念にカプセル化があります。

これは、必要のない内部詳細を外から隠し、決められた方法だけで操作させるという考え方です。

C++では、主に次の2つのアクセス指定子を使います。

  • public … クラスの外部からアクセス可能
  • private … クラスの内部からのみアクセス可能

実践的なクラスでは、データ(メンバ変数)はprivateにして、操作のための関数だけをpublicにすることが多いです。

C++
#include <iostream>
using namespace std;

class Account {
private:
    int balance; // 残高は外から直接いじらせない

public:
    // コンストラクタ
    Account(int initial) {
        if (initial < 0) {
            initial = 0;
        }
        balance = initial;
    }

    // 預け入れ
    void deposit(int amount) {
        if (amount > 0) {
            balance += amount;
        }
    }

    // 引き出し
    void withdraw(int amount) {
        if (amount > 0 && amount <= balance) {
            balance -= amount;
        }
    }

    // 残高取得
    int getBalance() const {
        return balance;
    }
};

int main() {
    Account acc(1000);       // 残高1000円で口座開設

    // acc.balance = 500;    // コンパイルエラー(privateのため)

    acc.deposit(500);        // 500円預ける
    acc.withdraw(300);       // 300円引き出す

    cout << "残高: " << acc.getBalance() << " 円" << endl;

    return 0;
}
実行結果
残高: 1200 円

このように「データは隠して、操作だけ公開する」という設計にすると、不正な値が入るのを防ぎ、クラスの使い方も分かりやすくなります。

アクセス指定子のまとめ

クラスでよく使うアクセス指定子を整理します。

指定子アクセス可能な範囲主な用途
publicどこからでもアクセス可能インターフェース(外部公開API)
privateクラスの内部(と友達宣言された関数・クラス)内部実装、守りたいデータや補助処理

迷ったら、まずはprivateで定義し、必要になったものだけpublicにするという方針にすると、安全な設計になりやすいです。

thisポインタと参照のイメージ

thisポインタとは

クラスのメンバ関数の中には、自分自身のオブジェクトを指すthisポインタが暗黙に渡されています。

ふだんは意識しなくても動きますが、同名の変数があるときなどに役立ちます。

C++
#include <iostream>
#include <string>
using namespace std;

class Player {
private:
    string name;

public:
    // 引数名とメンバ変数名が同じ場合、thisを使って区別できる
    Player(const string& name) {
        this->name = name; // this->name はメンバ変数
    }

    void show() const {
        cout << "プレイヤー名: " << name << endl;
        // 実際は this->name と同じ意味
    }
};

int main() {
    Player p("Carol");
    p.show();

    return 0;
}
実行結果
プレイヤー名: Carol

thisは「いま処理しているオブジェクト」へのポインタだと理解しておけば十分です。

慣れてくると、メソッドチェーンのような書き方を実現するために*thisを戻り値にする、といった応用もできます。

実用的なクラスのミニサンプル

簡単な「長方形クラス」を作ってみる

ここまで学んだ内容を組み合わせて、少し実用的なクラスを作ってみます。

長方形のサイズを管理し、面積や周の長さを計算できるクラスです。

C++
#include <iostream>
using namespace std;

// 長方形を表すクラス
class Rectangle {
private:
    double width;   // 幅
    double height;  // 高さ

public:
    // デフォルトコンストラクタ
    Rectangle() {
        width = 0.0;
        height = 0.0;
    }

    // 幅と高さを指定するコンストラクタ
    Rectangle(double w, double h) {
        setSize(w, h); // 共通のチェック処理を使う
    }

    // 幅と高さをまとめて設定する
    void setSize(double w, double h) {
        if (w < 0) w = 0;
        if (h < 0) h = 0;
        width = w;
        height = h;
    }

    // 幅だけ設定
    void setWidth(double w) {
        if (w < 0) w = 0;
        width = w;
    }

    // 高さだけ設定
    void setHeight(double h) {
        if (h < 0) h = 0;
        height = h;
    }

    // 幅を取得
    double getWidth() const {
        return width;
    }

    // 高さを取得
    double getHeight() const {
        return height;
    }

    // 面積を計算
    double area() const {
        return width * height;
    }

    // 周の長さを計算
    double perimeter() const {
        return 2 * (width + height);
    }

    // 情報を表示
    void show() const {
        cout << "幅: " << width
             << ", 高さ: " << height
             << ", 面積: " << area()
             << ", 周の長さ: " << perimeter()
             << endl;
    }
};

int main() {
    Rectangle r1;                // 0,0の長方形
    Rectangle r2(3.0, 4.0);     // 3×4の長方形

    r1.setSize(5.0, 2.0);       // 後からサイズを設定

    r1.show();
    r2.show();

    // ゲッターを使って値を取り出す
    cout << "r2の幅は " << r2.getWidth()
         << ", 高さは " << r2.getHeight() << endl;

    return 0;
}
実行結果
幅: 5, 高さ: 2, 面積: 10, 周の長さ: 14
幅: 3, 高さ: 4, 面積: 12, 周の長さ: 14
r2の幅は 3, 高さは 4

このクラスには次のような特徴があります。

  • 幅と高さはprivateで隠し、不正な値(負数)を避ける
  • 大きさを設定するためのメンバ関数をpublicで提供
  • 面積や周の長さといった「長方形らしい動作」をメンバ関数で表現

「データ + データに関する処理 = クラス」というイメージがつかみやすい例になっています。

まとめ

クラスは、C++で大きなプログラムを構築するための基本単位です。

本記事では、クラス定義の書き方、メンバ変数とメンバ関数、コンストラクタとデストラクタ、public/privateによるカプセル化、そしてthisポインタの役割までを一通り見てきました。

まずは「1つの概念を1つのクラスとしてまとめる」ことを意識し、シンプルなクラスから実際に書いてみることで、クラスの使い方に自然と慣れていくはずです。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!