読み込み中...

【C++】初心者でも理解できるゲッターとセッターの完全ガイド7選

C++におけるゲッターとセッターの使い方を解説する記事のサムネイル C++
この記事は約17分で読めます。

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

本記事のサンプルコードを活用して機能追加、目的を達成できるように作ってありますので、是非ご活用ください。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を満たす現役のプログラマチームによって監修されています。

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

C++プログラミングを学び始めた皆さん、あるいは既に一定の経験をお持ちの方々にとって、ゲッターとセッターは重要な概念です。

この記事を通して、ゲッターとセッターがC++プログラミングにおいてどのような役割を果たし、どのように活用されるのかを理解することができるでしょう。

具体的な例と共に、これらのメソッドがオブジェクト指向プログラミングの基本となるエンカプセレーション(カプセル化)の理念にどのように貢献するかを学ぶことができます。

●C++でのゲッターとセッターとは

C++でのゲッター(Getter)とセッター(Setter)は、オブジェクトの状態を管理するためのメソッドです。

ゲッターはオブジェクトの特定のプロパティを取得するために使われ、セッターはそのプロパティを設定または更新するために用います。

これらのメソッドは、オブジェクトの内部状態を外部から直接変更することなく、間接的に操作することを可能にします。

この機能は、オブジェクト指向の重要な特徴であるカプセル化と密接に関連しています。

○ゲッターとセッターの基本概念

ゲッターは、クラスの外部からクラスのメンバ変数の値を読み取るために使用されます。

通常、これらは引数を取らず、呼び出されたメンバ変数の値を返します。

一方で、セッターはクラスのメンバ変数に値を設定するために使用され、外部から渡された値を引数として受け取り、メンバ変数にその値を設定します。

これにより、オブジェクトの状態を制御しやすくなります。

○C++におけるゲッターとセッターの役割

C++において、ゲッターとセッターはエンカプセレーションを実現する重要な手段です。

エンカプセレーションとは、オブジェクトの詳細を隠蔽し、外部からの直接的なアクセスを制限することで、データの整合性を保つプログラミングの原則です。

ゲッターとセッターを使用することで、クラスの内部構造を外部から隠し、外部からは公開されたインターフェースを通してのみアクセスを許すことができます。

これにより、データの不正な利用や意図しないエラーからプログラムを保護することができるのです。

●ゲッターとセッターの基本的な使い方

C++では、オブジェクト指向プログラミングの基本要素として、ゲッターとセッターがよく使用されます。

これらは、クラスのプライベート変数へのアクセスを制御し、オブジェクトの状態を管理する重要な方法です。

ゲッターは、特定のプロパティの値を取得するために使用され、セッターはその値を設定するために使用されます。

ここでは、これらの基本的な使い方を詳しく見ていきましょう。

○サンプルコード1:基本的なゲッターの作り方

ここでは、C++での基本的なゲッターの作成方法について解説します。

ゲッターはクラス内のプライベート変数の値を外部から読み取ることができるメソッドです。

下記の例では、MyClass クラス内に value というプライベート変数があり、その値を取得するためのゲッター getValue を実装しています。

class MyClass {
private:
    int value;

public:
    MyClass(int val) : value(val) {}

    int getValue() const {
        return value;
    }
};

int main() {
    MyClass obj(100);
    std::cout << "The value is: " << obj.getValue() << std::endl;
    return 0;
}

この例では、MyClass オブジェクト obj を作成し、コンストラクタで value100 を設定しています。

getValue メソッドを呼び出すことで、value の値を取得し、出力しています。

const キーワードは、このメソッドがオブジェクトの状態を変更しないことを示しています。

○サンプルコード2:基本的なセッターの作り方

セッターは、クラスのプライベート変数に値を設定するために使われるメソッドです。

下記の例では、MyClasssetValue というセッターを追加し、外部から value の値を設定できるようにしています。

class MyClass {
private:
    int value;

public:
    MyClass(int val) : value(val) {}

    void setValue(int val) {
        value = val;
    }

    int getValue() const {
        return value;
    }
};

int main() {
    MyClass obj(100);
    obj.setValue(200);
    std::cout << "The updated value is: " << obj.getValue() << std::endl;
    return 0;
}

このサンプルコードでは、初めに MyClass のオブジェクト obj を生成し、コンストラクタで value100 に設定しています。

その後、setValue メソッドを使って value200 に更新し、改めて getValue メソッドで値を取得して出力しています。

●ゲッターとセッターの応用例

C++のゲッターとセッターは基本的な使い方だけでなく、さまざまな応用が可能です。

これらを使って、より効率的で安全なコードを書く方法を見ていきましょう。

○サンプルコード3:条件付きセッターの実装

条件付きセッターは、特定の条件を満たす場合にのみ値を設定するメソッドです。

この例では、ある数値が特定の範囲内にある場合のみ、その値をセットする方法を表しています。

class MyClass {
private:
    int value;

public:
    MyClass(int val) : value(val) {}

    bool setValue(int val) {
        if (val >= 0 && val <= 100) {
            value = val;
            return true;
        }
        return false;
    }

    int getValue() const {
        return value;
    }
};

int main() {
    MyClass obj(50);
    if (obj.setValue(30)) {
        std::cout << "Value set to 30" << std::endl;
    } else {
        std::cout << "Value out of range" << std::endl;
    }
    return 0;
}

このコードでは、setValue メソッドが 0 から 100 の範囲内の値のみを受け入れるように設定されています。

これにより、不適切な値が設定されるのを防ぐことができます。

○サンプルコード4:ゲッターを使った情報のカプセル化

ゲッターは、クラスの内部情報をカプセル化するのにも役立ちます。

この例では、内部情報を直接公開せず、必要な情報のみを提供する方法を表しています。

class Employee {
private:
    std::string name;
    int age;

public:
    Employee(std::string n, int a) : name(n), age(a) {}

    std::string getInfo() const {
        return "Name: " + name + ", Age: " + std::to_string(age);
    }
};

int main() {
    Employee emp("Alice", 30);
    std::cout << emp.getInfo() << std::endl;
    return 0;
}

このコードでは、Employee クラスの nameage がプライベートとなっており、getInfo メソッドを通じてのみアクセス可能です。

これにより、オブジェクトのデータを適切に隠蔽し、コントロールすることができます。

○サンプルコード5:セッターでのデータ検証

セッターはデータの検証にも使うことができます。

例えば、文字列が特定のフォーマットに合っているかをチェックすることができます。

class User {
private:
    std::string email;

public:
    bool setEmail(const std::string& mail) {
        if (mail.find('@') != std::string::npos) {
            email = mail;
            return true;
        }
        return false;
    }

    std::string getEmail() const {
        return email;
    }
};

int main() {
    User user;
    if (user.setEmail("user@example.com")) {
        std::cout << "Email set to " << user.getEmail() << std::endl;
    } else {
        std::cout << "Invalid email" << std::endl;
    }
    return 0;
}

この例では、setEmail メソッドが @ 文字を含むかどうかをチェックしています。

このようにして、無効なデータの設定を防ぐことができます。

●エンカプセレーションとゲッター/セッター

オブジェクト指向プログラミングにおける重要な概念の一つがエンカプセレーション、つまりカプセル化です。

これは、オブジェクトの内部状態を外部から隠蔽し、オブジェクト自身のメソッドを通じてのみ内部状態にアクセスすることを指します。

C++でのエンカプセレーションは、主にプライベート変数と公開メソッド(特にゲッターとセッター)を使用して実装されます。

○エンカプセレーションの重要性

エンカプセレーションにより、クラスの内部実装を隠蔽することができます。

これは、オブジェクトのデータを直接操作することを防ぎ、不正な値が設定されることを防ぐために重要です。

また、クラスの利用者に対しては、必要な情報のみを提供し、クラスの使用を簡素化します。

これにより、プログラムの保守性が向上し、エラーの可能性が減少します。

○ゲッター/セッターを用いたエンカプセレーションの実例

下記のサンプルコードは、C++でエンカプセレーションを実装する方法を表しています。

ここでは、Personクラスを定義し、nameageのプライベートメンバ変数に対してゲッターとセッターを提供しています。

class Person {
private:
    std::string name;
    int age;

public:
    Person(std::string n, int a) : name(n), age(a) {}

    // ゲッター
    std::string getName() const {
        return name;
    }

    int getAge() const {
        return age;
    }

    // セッター
    void setName(const std::string& newName) {
        name = newName;
    }

    void setAge(int newAge) {
        if (newAge >= 0) {
            age = newAge;
        }
    }
};

int main() {
    Person person("Alice", 25);
    person.setAge(30);
    std::cout << person.getName() << " is " << person.getAge() << " years old." << std::endl;
    return 0;
}

この例では、Personオブジェクトのnameageを直接操作する代わりに、setNamesetAgeメソッドを通じてこれらの値を設定しています。

setAgeメソッドでは、年齢が負の数でないことを確認することで、無効な値の設定を防いでいます。

これにより、Personクラスのインスタンスの状態は、常に一貫性を保つことができます。

●よくある間違いとその対処法

C++におけるゲッターとセッターの使用では、特に初心者が陥りやすいいくつかの間違いがあります。

これらの間違いを理解し、適切な対処法を学ぶことは、より効率的で安全なコーディングにつながります。

○間違ったゲッター/セッターの使用例

一つの典型的な間違いは、ゲッターとセッターを過剰に使用することです。

すべての変数に対してゲッターとセッターを用意すると、クラスの設計が冗長になり、保守が難しくなる可能性があります。

また、不必要に内部状態を公開しすぎると、クラスのカプセル化が破壊され、オブジェクトの整合性が損なわれることがあります。

もう一つの間違いは、セッター内での不適切なデータ検証です。

例えば、数値を受け取るセッターが負の値を誤って受け入れることなどが考えられます。

これにより、プログラムに予期せぬバグや脆弱性が発生する可能性があります。

○間違いの対処法とベストプラクティス

これらの間違いに対処するためには、まずゲッターとセッターの適切な使用を心掛けることが重要です。

すべてのメンバ変数にゲッターとセッターを設けるのではなく、外部からアクセスが必要な場合のみこれらのメソッドを提供するようにしましょう。

セッターを実装する際には、適切なデータ検証を行うことが重要です。

値が特定の条件を満たしているかどうかをチェックし、条件を満たさない場合は値の設定を拒否するか、適切な例外処理を行うようにしましょう。

また、ゲッターとセッターの命名規則を一貫させ、クラスの外部からのアクセスを容易に理解できるようにすることも重要です。

例えば、getValuesetValueのような明確な命名を使用し、メソッドの目的を一目で理解できるようにしましょう。

●C++におけるゲッターとセッターの応用技術

C++におけるゲッターとセッターは基本的な機能を超えて、さまざまな応用技術を使用することが可能です。

これにより、プログラムの柔軟性や効率性が向上し、より洗練されたコードを書くことができます。

○サンプルコード6:オーバーロードされたセッター

セッターはオーバーロードすることができ、異なるタイプの引数を受け取ることが可能です。

下記の例では、異なるデータタイプの引数を受け取るセッターをオーバーロードしています。

class Example {
private:
    int intValue;
    std::string stringValue;

public:
    void setValue(int value) {
        intValue = value;
    }

    void setValue(const std::string& value) {
        stringValue = value;
    }

    int getIntValue() const {
        return intValue;
    }

    std::string getStringValue() const {
        return stringValue;
    }
};

int main() {
    Example example;
    example.setValue(10);
    example.setValue("Hello");
    std::cout << "Integer: " << example.getIntValue() << ", String: " << example.getStringValue() << std::endl;
    return 0;
}

このコードでは、setValueメソッドが整数型と文字列型の両方の引数を受け取ることができるようにオーバーロードされています。

これにより、同じメソッド名で異なるタイプのデータを扱うことができます。

○サンプルコード7:インラインゲッター/セッターの使用

インラインゲッターとセッターは、コードの可読性を高め、記述量を減らすために使用されます。

これらはクラスの定義内に直接実装され、コンパイラによって自動的にインライン化されることがあります。

class CompactExample {
private:
    int data;

public:
    void setData(int d) { data = d; }
    int getData() const { return data; }
};

int main() {
    CompactExample example;
    example.setData(100);
    std::cout << "Data: " << example.getData() << std::endl;
    return 0;
}

この例では、setDatagetDataメソッドがクラス内にインラインで実装されています。

これにより、メソッドの宣言と定義が1か所にまとまり、コードがシンプルで読みやすくなっています。

●エンジニアが知るべきC++の豆知識

C++プログラミングにおいて、エンジニアが押さえておくべきいくつかの重要なポイントがあります。

これらの知識は、より効果的で効率的なプログラミングを実現するために役立ちます。

○豆知識1:ゲッター/セッターとメモリ管理

C++では、ゲッターとセッターを使用する際にメモリ管理が重要になります。

特に、大きなデータ構造やリソースを扱う場合、不適切なメモリ管理はパフォーマンスの低下やメモリリークを引き起こす可能性があります。

例えば、大きなデータを返すゲッターを作成する際には、値渡しではなく参照渡しやポインタ渡しを使用することで、不必要なデータのコピーを避けることができます。

class LargeData {
private:
    std::vector<int> data;

public:
    const std::vector<int>& getData() const {
        return data;
    }

    void setData(const std::vector<int>& newData) {
        data = newData;
    }
};

この例では、std::vector<int>の大量のデータを扱っていますが、getDataメソッドはデータの参照を返すことで、データのコピーを防いでいます。

○豆知識2:パフォーマンスへの影響

C++のゲッターとセッターの使用はパフォーマンスにも影響を及ぼすことがあります。

特に、ゲッターやセッターが頻繁に呼び出される大規模なプログラムでは、これらのメソッドのオーバーヘッドが無視できないほどになることがあります。

パフォーマンスに敏感なアプリケーションでは、インライン関数を利用することで、関数呼び出しのコストを削減できます。

class PerformanceSensitive {
private:
    int value;

public:
    inline void setValue(int newValue) {
        value = newValue;
    }

    inline int getValue() const {
        return value;
    }
};

この例では、setValuegetValueメソッドがインライン関数として定義されており、関数呼び出しのオーバーヘッドを削減しています。

このように、C++ではメモリ管理とパフォーマンスの両方を意識することが重要です。

まとめ

この記事では、C++におけるゲッターとセッターの概念、基本的な使い方から応用技術に至るまでを詳しく解説しました。

初心者から上級者までが理解できるように、具体的なサンプルコードを用いて実践的な内容を紹介しました。

ゲッターとセッターの正しい使用法をマスターすることは、エンカプセレーションを強化し、より安全で保守しやすいC++プログラミングを実現する重要な要素となります。