MENU

C++ クラスの練習

C++プログラミングにおいて、クラスの理解と活用は非常に重要です。クラスを使いこなすことで、より構造化され、保守性の高いコードを書くことができます。本記事では、C++初心者の方向けに、クラスの基本概念から実践的な使用方法まで、段階的に学んでいきます。具体的な例と練習問題を通じて、クラスの作成と使用方法をマスターしましょう。

目次

クラスの基本

クラスは、データ(メンバ変数)と、そのデータを操作する関数(メンバ関数)をひとまとめにした「設計図」のようなものです。クラスを使うことで、現実世界の概念やオブジェクトをプログラム内で表現しやすくなります。

まずは、簡単な「長方形」クラスを作成して、クラスの基本構造を理解しましょう。

#include <iostream>

class Rectangle {
private:
    double width;
    double height;

public:
    // コンストラクタ
    Rectangle(double w, double h) : width(w), height(h) {}

    // メンバ関数
    double calculateArea() {
        return width * height;
    }

    void displayInfo() {
        std::cout << "幅: " << width << ", 高さ: " << height 
                  << ", 面積: " << calculateArea() << std::endl;
    }
};

int main() {
    Rectangle rect(5.0, 3.0);
    rect.displayInfo();
    return 0;
}

このコードでは、Rectangleクラスを定義しています。クラスの構造を詳しく見ていきましょう:

  1. private:セクションでは、クラスの外部からアクセスできないメンバ変数(widthheight)を定義しています。
  2. public:セクションでは、クラスの外部からアクセス可能なメンバ関数を定義しています。
  3. Rectangle(double w, double h)はコンストラクタで、オブジェクトの作成時に呼び出されます。
  4. calculateArea()displayInfo()はメンバ関数で、それぞれ面積の計算と情報の表示を行います。

main()関数では、Rectangleクラスのオブジェクトを作成し、そのdisplayInfo()メンバ関数を呼び出しています。

練習1: 円クラスの作成

では、上記の例を参考に、円を表すCircleクラスを作成してみましょう。このクラスには以下の要素を含めてください:

  • 半径を表すprivateメンバ変数
  • 半径を設定するコンストラクタ
  • 円の面積を計算するメンバ関数
  • 円の周囲の長さを計算するメンバ関数
  • 円の情報を表示するメンバ関数

以下に、解答例を示します:

#include <iostream>
#include <cmath>

class Circle {
private:
    double radius;
    const double PI = 3.14159265358979323846;

public:
    // コンストラクタ
    Circle(double r) : radius(r) {}

    // 面積を計算
    double calculateArea() {
        return PI * radius * radius;
    }

    // 周囲の長さを計算
    double calculateCircumference() {
        return 2 * PI * radius;
    }

    // 情報を表示
    void displayInfo() {
        std::cout << "半径: " << radius 
                  << ", 面積: " << calculateArea() 
                  << ", 周囲の長さ: " << calculateCircumference() << std::endl;
    }
};

int main() {
    Circle circle(5.0);
    circle.displayInfo();
    return 0;
}

このクラスでは、calculateArea()calculateCircumference()という二つの計算用メンバ関数を追加しています。これらの関数はdisplayInfo()内で呼び出され、円の情報を表示します。

ゲッターとセッター

クラスの設計において、カプセル化は重要な概念です。プライベートメンバ変数に対して、ゲッター(値を取得する関数)とセッター(値を設定する関数)を提供することで、データの整合性を保ちつつ、必要に応じて値の取得や変更が可能になります。

先程のCircleクラスにゲッターとセッターを追加してみましょう:

class Circle {
private:
    double radius;
    const double PI = 3.14159265358979323846;

public:
    Circle(double r) : radius(r) {}

    // ゲッター
    double getRadius() const {
        return radius;
    }

    // セッター
    void setRadius(double r) {
        if (r > 0) {
            radius = r;
        } else {
            std::cout << "エラー: 半径は正の値でなければなりません。" << std::endl;
        }
    }

    // 他のメンバ関数は省略...
};

int main() {
    Circle circle(5.0);
    std::cout << "現在の半径: " << circle.getRadius() << std::endl;
    
    circle.setRadius(7.0);
    std::cout << "変更後の半径: " << circle.getRadius() << std::endl;
    
    circle.setRadius(-2.0);  // エラーメッセージが表示される
    
    return 0;
}

この例では、getRadius()ゲッターとsetRadius()セッターを追加しています。セッターでは、新しい半径が正の値であることを確認し、不適切な値が設定されるのを防いでいます。

練習2: 銀行口座クラスの作成

次に、より実践的な例として、銀行口座を表すBankAccountクラスを作成してみましょう。このクラスには以下の要素を含めてください:

  • 口座番号と残高を表すprivateメンバ変数
  • コンストラクタ(口座番号を設定し、初期残高を0にする)
  • 預金と引き出しを行うメンバ関数
  • 残高を取得するゲッター
  • 口座情報を表示するメンバ関数

以下に、解答例を示します:

#include <iostream>
#include <string>

class BankAccount {
private:
    std::string accountNumber;
    double balance;

public:
    // コンストラクタ
    BankAccount(const std::string& accNum) : accountNumber(accNum), balance(0.0) {}

    // 預金
    void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
            std::cout << amount << "円を預けました。" << std::endl;
        } else {
            std::cout << "エラー: 預金額は正の値でなければなりません。" << std::endl;
        }
    }

    // 引き出し
    void withdraw(double amount) {
        if (amount > 0) {
            if (balance >= amount) {
                balance -= amount;
                std::cout << amount << "円を引き出しました。" << std::endl;
            } else {
                std::cout << "エラー: 残高が不足しています。" << std::endl;
            }
        } else {
            std::cout << "エラー: 引き出し額は正の値でなければなりません。" << std::endl;
        }
    }

    // 残高を取得(ゲッター)
    double getBalance() const {
        return balance;
    }

    // 口座情報を表示
    void displayInfo() const {
        std::cout << "口座番号: " << accountNumber << ", 残高: " << balance << "円" << std::endl;
    }
};

int main() {
    BankAccount account("1234567890");
    account.displayInfo();
    
    account.deposit(10000);
    account.displayInfo();
    
    account.withdraw(3000);
    account.displayInfo();
    
    account.withdraw(8000);  // エラーメッセージが表示される
    
    return 0;
}

このBankAccountクラスでは、以下のような特徴があります:

  1. コンストラクタで口座番号を設定し、初期残高を0に設定しています。
  2. deposit()withdraw()メソッドで、預金と引き出しの処理を行います。これらのメソッドには、不正な操作(負の金額の入力や残高不足など)をチェックする機能があります。
  3. getBalance()ゲッターで、現在の残高を取得できます。
  4. displayInfo()メソッドで、口座の情報を表示します。

この例では、実際の銀行口座の基本的な機能を模倣しています。エラーチェックを含めることで、より堅牢なクラス設計になっています。

C++でクラスを作成し使用することは、オブジェクト指向プログラミングの基礎となる重要なスキルです。この記事で紹介した基本的な概念と練習問題を通じて、クラスの設計と実装について理解を深めることができます。

クラスを適切に設計し利用することで、より構造化され、保守性の高いプログラムを作成することができます。さらに学習を進めると、継承やポリモーフィズム、テンプレートクラスなど、より高度なC++の機能を使いこなせるようになり、より柔軟で強力なプログラムを作成できるようになります。

練習を重ね、様々な状況でクラスを使用することで、オブジェクト指向プログラミングのスキルを向上させることができます。例えば、学生管理システム、在庫管理システム、ゲームのキャラクター設計など、実際のアプリケーションを想定したクラス設計の練習を行うことをお勧めします。

C++プログラミングの世界は奥深く、常に新しいことを学ぶ機会があります。基礎をしっかり固めた上で、少しずつ高度な概念に挑戦していくことで、より効果的に学習を進めることができるでしょう。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次