[C++] クラスのthisポインタの使い方をわかりやすく解説

C++におけるthisポインタは、クラスのメンバ関数内で使用される特殊なポインタで、関数が呼び出されたオブジェクト自身を指します。

thisは、メンバ変数とローカル変数の名前が衝突した場合に、オブジェクトのメンバ変数を明示的に参照するために使われます。

また、メンバ関数内でオブジェクト自身を返す際にも使用されます。

例えば、return *this;とすることで、現在のオブジェクトを返すことができます。

この記事でわかること
  • thisポインタの基本的な役割
  • メンバ関数内での使い方
  • メソッドチェーンの実装方法
  • constメンバ関数の特性
  • thisポインタの誤用によるリスク

目次から探す

thisポインタとは何か

C++におけるthisポインタは、クラスのメンバ関数内で使用される特別なポインタです。

このポインタは、呼び出されたメンバ関数が属するオブジェクト自身を指します。

これにより、オブジェクトのメンバ変数や他のメンバ関数にアクセスすることが可能になります。

thisポインタの基本的な役割

thisポインタの主な役割は、メンバ関数がどのオブジェクトに対して呼び出されたかを示すことです。

これにより、同じクラスの異なるオブジェクト間でのデータの管理が容易になります。

クラスメンバ関数内でのthisポインタの使い方

クラスのメンバ関数内でthisポインタを使用することで、オブジェクトのメンバ変数にアクセスできます。

以下はその例です。

#include <iostream>
using namespace std;
class MyClass {
public:
    int value;
    MyClass(int v) : value(v) {}
    void showValue() {
        // thisポインタを使ってメンバ変数にアクセス
        cout << "Value: " << this->value << endl;
    }
};
int main() {
    MyClass obj(10);
    obj.showValue();
    return 0;
}
Value: 10

この例では、showValueメンバ関数内でthisポインタを使用して、オブジェクトのvalueメンバ変数にアクセスしています。

thisポインタの型と性質

thisポインタの型は、クラスのポインタ型です。

例えば、クラスMyClassのメンバ関数内でのthisポインタの型はMyClass*となります。

この性質により、thisポインタを使って他のメンバ関数やメンバ変数にアクセスすることができます。

thisポインタが使われる場面

thisポインタは、以下のような場面で使用されます。

スクロールできます
使用場面説明
メンバ変数の参照同名のローカル変数と区別するために使用
メソッドチェーンの実装自分自身を返すことで連続した呼び出しを可能にする
コンストラクタの初期化オブジェクトの初期化時に使用
自己代入の防止自己代入を防ぐためのチェックに使用

これらの場面でthisポインタを活用することで、より効率的で安全なプログラミングが可能になります。

thisポインタの具体的な使い方

thisポインタは、クラスのメンバ関数内でさまざまな用途に利用されます。

以下では、具体的な使い方をいくつか紹介します。

メンバ変数とローカル変数の名前の衝突を解決する

メンバ変数とローカル変数が同じ名前の場合、thisポインタを使うことでメンバ変数を明示的に参照できます。

以下の例を見てみましょう。

#include <iostream>
using namespace std;
class MyClass {
public:
    int value;
    MyClass(int value) { // コンストラクタの引数とメンバ変数が同名
        this->value = value; // thisポインタを使ってメンバ変数を参照
    }
    void showValue() {
        cout << "Value: " << this->value << endl;
    }
};
int main() {
    MyClass obj(10);
    obj.showValue();
    return 0;
}
Value: 10

この例では、コンストラクタの引数valueメンバ変数valueが同名ですが、this->valueを使うことでメンバ変数を正しく参照しています。

メンバ関数でオブジェクト自身を返す

thisポインタを使うことで、メンバ関数がオブジェクト自身を返すことができます。

これにより、メソッドチェーンを実現できます。

#include <iostream>
using namespace std;
class MyClass {
public:
    int value;
    MyClass(int v) : value(v) {}
    MyClass* setValue(int v) {
        this->value = v; // メンバ変数に値を設定
        return this; // 自分自身を返す
    }
    void showValue() {
        cout << "Value: " << this->value << endl;
    }
};
int main() {
    MyClass obj(10);
    obj.setValue(20)->showValue(); // メソッドチェーン
    return 0;
}
Value: 20

この例では、setValueメンバ関数がthisポインタを返すことで、メソッドチェーンを実現しています。

メソッドチェーンでのthisポインタの活用

メソッドチェーンは、複数のメソッドを連続して呼び出す手法です。

thisポインタを使うことで、オブジェクト自身を返し、連続した操作を可能にします。

#include <iostream>
using namespace std;
class MyClass {
public:
    int value;
    MyClass(int v) : value(v) {}
    MyClass* increment() {
        this->value++; // 値をインクリメント
        return this; // 自分自身を返す
    }
    void showValue() {
        cout << "Value: " << this->value << endl;
    }
};
int main() {
    MyClass obj(5);
    obj.increment()->increment()->showValue(); // メソッドチェーン
    return 0;
}
Value: 7

この例では、incrementメソッドを2回呼び出し、最終的にshowValueメソッドで結果を表示しています。

コンストラクタやデストラクタでのthisポインタの使用

コンストラクタやデストラクタ内でもthisポインタを使用することができます。

これにより、オブジェクトの初期化やクリーンアップを行う際に、メンバ変数にアクセスできます。

#include <iostream>
using namespace std;
class MyClass {
public:
    int value;
    MyClass(int v) : value(v) {
        cout << "コンストラクタ: " << this->value << " が初期化されました。" << endl;
    }
    ~MyClass() {
        cout << "デストラクタ: " << this->value << " が破棄されました。" << endl;
    }
};
int main() {
    MyClass obj(10);
    return 0; // objのデストラクタが呼ばれる
}
コンストラクタ: 10 が初期化されました。
デストラクタ: 10 が破棄されました。

この例では、コンストラクタとデストラクタ内でthisポインタを使用して、オブジェクトの状態を表示しています。

thisポインタの応用例

thisポインタは、C++プログラミングにおいてさまざまな応用が可能です。

以下では、具体的な応用例をいくつか紹介します。

メソッドチェーンの実装

メソッドチェーンは、オブジェクトのメソッドを連続して呼び出す手法です。

thisポインタを使用することで、メソッドがオブジェクト自身を返し、連続した操作を可能にします。

#include <iostream>
using namespace std;
class MyClass {
public:
    int value;
    MyClass(int v) : value(v) {}
    MyClass* setValue(int v) {
        this->value = v; // 値を設定
        return this; // 自分自身を返す
    }
    MyClass* increment() {
        this->value++; // 値をインクリメント
        return this; // 自分自身を返す
    }
    void showValue() {
        cout << "Value: " << this->value << endl;
    }
};
int main() {
    MyClass obj(5);
    obj.setValue(10)->increment()->showValue(); // メソッドチェーン
    return 0;
}
Value: 11

この例では、setValueメソッドincrementメソッドを連続して呼び出し、最終的にshowValueメソッドで結果を表示しています。

自己代入の防止

thisポインタを使用することで、自己代入を防ぐためのチェックを行うことができます。

特に、オブジェクトのメンバ変数を別のオブジェクトで上書きする際に役立ちます。

#include <iostream>
using namespace std;
class MyClass {
public:
    int value;
    MyClass(int v) : value(v) {}
    MyClass& operator=(const MyClass& other) {
        if (this != &other) { // 自己代入のチェック
            this->value = other.value; // 値をコピー
        }
        return *this; // 自分自身を返す
    }
    void showValue() {
        cout << "Value: " << this->value << endl;
    }
};
int main() {
    MyClass obj1(10);
    MyClass obj2(20);
    obj1 = obj2; // 自己代入ではない
    obj1.showValue();
    obj1 = obj1; // 自己代入
    obj1.showValue();
    return 0;
}
Value: 20
Value: 20

この例では、operator=をオーバーロードし、自己代入を防ぐためにthisポインタを使用しています。

フルイドインターフェースの実装

フルイドインターフェースは、メソッドを連続して呼び出すことができるスタイルのプログラミングです。

thisポインタを使うことで、オブジェクトの状態を簡潔に設定できます。

#include <iostream>
using namespace std;
class MyClass {
public:
    int value;
    MyClass(int v) : value(v) {}
    MyClass* setValue(int v) {
        this->value = v; // 値を設定
        return this; // 自分自身を返す
    }
    MyClass* multiply(int factor) {
        this->value *= factor; // 値を乗算
        return this; // 自分自身を返す
    }
    void showValue() {
        cout << "Value: " << this->value << endl;
    }
};
int main() {
    MyClass obj(5);
    obj.setValue(10)->multiply(2)->showValue(); // フルイドインターフェース
    return 0;
}
Value: 20

この例では、setValueメソッドmultiplyメソッドを連続して呼び出し、最終的にshowValueメソッドで結果を表示しています。

オブジェクトのコピーとthisポインタ

thisポインタは、オブジェクトのコピーを行う際にも使用されます。

特に、コピーコンストラクタや代入演算子での自己代入チェックに役立ちます。

#include <iostream>
using namespace std;
class MyClass {
public:
    int value;
    MyClass(int v) : value(v) {}
    MyClass(const MyClass& other) { // コピーコンストラクタ
        this->value = other.value; // 値をコピー
    }
    void showValue() {
        cout << "Value: " << this->value << endl;
    }
};
int main() {
    MyClass obj1(10);
    MyClass obj2 = obj1; // コピーコンストラクタが呼ばれる
    obj2.showValue();
    return 0;
}
Value: 10

この例では、コピーコンストラクタ内でthisポインタを使用して、他のオブジェクトから値をコピーしています。

スマートポインタとthisポインタの関係

スマートポインタは、メモリ管理を自動化するためのクラスです。

thisポインタを使用することで、スマートポインタ内のオブジェクトにアクセスできます。

#include <iostream>
#include <memory>
using namespace std;
class MyClass {
public:
    int value;
    MyClass(int v) : value(v) {}
    void showValue() {
        cout << "Value: " << this->value << endl;
    }
};
int main() {
    unique_ptr<MyClass> obj = make_unique<MyClass>(10);
    obj->showValue(); // thisポインタを使ってメンバ関数を呼び出す
    return 0;
}
Value: 10

この例では、unique_ptrを使用してMyClassのインスタンスを管理し、thisポインタを使ってメンバ関数を呼び出しています。

スマートポインタを使用することで、メモリ管理が簡素化されます。

thisポインタの制約と注意点

thisポインタは非常に便利ですが、使用する際にはいくつかの制約や注意点があります。

以下では、これらのポイントについて詳しく説明します。

staticメンバ関数ではthisポインタは使えない

staticメンバ関数は、クラスのインスタンスに依存しないため、thisポインタを使用することができません。

staticメンバ関数は、クラス全体に関連付けられており、特定のオブジェクトにアクセスすることができません。

#include <iostream>
using namespace std;
class MyClass {
public:
    static void staticFunction() {
        // thisポインタは使用できない
        // cout << this->value << endl; // エラー
        cout << "Static function called." << endl;
    }
};
int main() {
    MyClass::staticFunction(); // staticメンバ関数の呼び出し
    return 0;
}
Static function called.

この例では、staticFunction内でthisポインタを使用しようとするとエラーになります。

constメンバ関数でのthisポインタの扱い

constメンバ関数は、オブジェクトの状態を変更しないことを保証します。

このため、constメンバ関数内でのthisポインタは、const修飾子が付いたポインタとして扱われます。

つまり、constメンバ関数内では、メンバ変数を変更することができません。

#include <iostream>
using namespace std;
class MyClass {
public:
    int value;
    MyClass(int v) : value(v) {}
    void showValue() const {
        cout << "Value: " << this->value << endl; // OK
        // this->value = 20; // エラー: constメンバ関数内での変更は不可
    }
};
int main() {
    MyClass obj(10);
    obj.showValue();
    return 0;
}
Value: 10

この例では、showValueメンバ関数がconstとして定義されているため、thisポインタはconst MyClass*として扱われ、メンバ変数を変更することはできません。

thisポインタの無効化とそのリスク

thisポインタは、オブジェクトが無効化された場合(例えば、デストラクタが呼ばれた後)に使用すると、未定義の動作を引き起こす可能性があります。

無効なオブジェクトに対してthisポインタを使用すると、プログラムがクラッシュすることがあります。

#include <iostream>
using namespace std;
class MyClass {
public:
    MyClass() {
        cout << "Constructor called." << endl;
    }
    ~MyClass() {
        cout << "Destructor called." << endl;
    }
    void showValue() {
        cout << "Value accessed." << endl;
    }
};
int main() {
    MyClass* obj = new MyClass();
    delete obj; // オブジェクトが無効化される
    // obj->showValue(); // エラー: 無効なオブジェクトへのアクセス
    return 0;
}
Constructor called.
Destructor called.

この例では、deleteによってオブジェクトが無効化された後に、そのオブジェクトに対してメソッドを呼び出すと、未定義の動作が発生します。

thisポインタの誤用によるバグの例

thisポインタの誤用は、バグの原因となることがあります。

特に、thisポインタを誤って他のオブジェクトに渡すと、意図しない動作を引き起こすことがあります。

#include <iostream>
using namespace std;
class MyClass {
public:
    int value;
    MyClass(int v) : value(v) {}
    void showValue() {
        cout << "Value: " << this->value << endl;
    }
    void setValue(MyClass* other) {
        this->value = other->value; // 他のオブジェクトの値を設定
    }
};
int main() {
    MyClass obj1(10);
    MyClass obj2(20);
    obj1.setValue(&obj2); // obj1の値がobj2の値に上書きされる
    obj1.showValue(); // 20が表示される
    return 0;
}
Value: 20

この例では、setValueメソッドthisポインタを使って他のオブジェクトの値を設定しています。

意図しないオブジェクトの値の上書きが発生する可能性があるため、注意が必要です。

よくある質問

thisポインタはいつ自動的に渡されるのか?

thisポインタは、クラスのメンバ関数が呼び出される際に自動的に渡されます。

具体的には、オブジェクトのメンバ関数を呼び出すと、その関数内でthisポインタが自動的に生成され、呼び出されたオブジェクトを指します。

これにより、メンバ変数や他のメンバ関数にアクセスすることが可能になります。

thisポインタを明示的に渡すことはできるのか?

thisポインタを明示的に渡すことは可能です。

例えば、メンバ関数の引数としてthisポインタを渡すことができます。

ただし、通常はthisポインタを明示的に渡す必要はなく、メンバ関数内で自動的に利用することが一般的です。

#include <iostream>
using namespace std;
class MyClass {
public:
    int value;
    MyClass(int v) : value(v) {}
    void showValue() {
        cout << "Value: " << this->value << endl;
    }
    void passThis(MyClass* obj) {
        obj->showValue(); // 明示的にthisポインタを渡す
    }
};
int main() {
    MyClass obj(10);
    obj.passThis(&obj); // thisポインタを明示的に渡す
    return 0;
}
Value: 10

この例では、passThisメソッドthisポインタを明示的に渡しています。

thisポインタを使わないとどうなるのか?

thisポインタを使わない場合、特にメンバ変数や他のメンバ関数にアクセスする際に、名前の衝突が発生する可能性があります。

例えば、メンバ変数とローカル変数が同じ名前の場合、thisポインタを使わないと、ローカル変数が優先されてしまいます。

#include <iostream>
using namespace std;
class MyClass {
public:
    int value;
    MyClass(int v) : value(v) {}
    void setValue(int value) {
        // thisポインタを使わないとローカル変数が優先される
        value = value; // 何も変更されない
    }
    void showValue() {
        cout << "Value: " << this->value << endl;
    }
};
int main() {
    MyClass obj(10);
    obj.setValue(20); // 何も変更されない
    obj.showValue(); // 10が表示される
    return 0;
}
Value: 10

この例では、setValueメソッド内でthisポインタを使わなかったため、メンバ変数valueは変更されず、元の値が表示されます。

thisポインタを使用することで、メンバ変数を正しく参照し、意図した通りに値を設定することができます。

まとめ

この記事では、C++におけるthisポインタの基本的な役割や具体的な使い方、応用例、制約と注意点について詳しく解説しました。

thisポインタは、オブジェクトのメンバ関数内で自分自身を参照するための重要な機能であり、メンバ変数や他のメンバ関数へのアクセスを容易にします。

これを活用することで、より効率的で安全なプログラミングが可能になりますので、ぜひ実際のコードに取り入れてみてください。

当サイトはリンクフリーです。出典元を明記していただければ、ご自由に引用していただいて構いません。

関連カテゴリーから探す

  • URLをコピーしました!
目次から探す