★thisポインタ★


クラスには自分自身のアドレスを保持する「thisポインタ」が用意されています。

頻繁に使うものではありませんが、知らなければ出来ない事もあります。

まずは、メモリのイメージを書いておきます。

            クラスの実体
           +------------+
  00E3F8C0 |            |
           |            |
           |            |
           |            |
           |            |
           |            |
           +------------+

あるクラスの実体が「00E3F8C0番地」に作られました。

このクラスには、thisという名前のポインタ変数が自動的に用意され、そのクラスのアドレスが入っています。

            クラスの実体
           +------------+
  00E3F8C0 |            |
           |            |
           |            |
           |            |
           |            |
           +------------+
      this |  00E3F8C0  |
           +------------+

privateなため、クラスの外からは使えません。


では、サンプルプログラムを1つ書きます。

<sample program col_cpp002-01>

#include <iostream>

class Enemy {
public:

    void SetHP(const int hp);

private:

    int m_hp;
};

int main()
{
    Enemy enemy;

    enemy.SetHP(150);

    return 0;
}

void Enemy::SetHP(const int hp)
{
    this->m_hp = hp;
}

メンバ変数の「m_hp」を使う前に、「this->」を付けました。

正直付けなくても動きます(省略可と言う事です)。

クラスのポインタなので、構造体と同じように「->演算子」でメンバにアクセスします。


上の例はあまり意味が無かったのですが、↓の状況ではどうでしょう。

メンバ変数の名前を「hp」として、引数と同じ名前にしてみます。

最初は「thisポインタ」を使わずに代入してみましょう。

<sample program col_cpp002-02>

#include <iostream>

class Enemy {
public:

    void SetHP(const int hp);

private:

    int hp;
};

int main()
{
    Enemy enemy;

    enemy.SetHP(150);

    return 0;
}

void Enemy::SetHP(const int hp)
{
    hp = hp;
}

<コンパイル結果>

error C3892: 'hp': const である変数へは割り当てることはできません

エラーになりました。

注目すべきは、

void Enemy::SetHP(const int hp)
{
    hp = hp;
}

です。

私としては、

 (メンバ変数の)hp =(引数の)hp;

としたつもりでしたが、エラーメッセージを見る限り

 (引数の)hp =(引数の)hp;

となっているようです。

同じ名前ですからコンパイラも区別は付きません・・・

そこで「thisポインタ」の出番です。

メンバ変数の「hp」の前に付ける事で、引数の「hp」と区別する事が出来ます。

<sample program col_cpp002-03>

#include <iostream>

class Enemy {
public:

    void SetHP(const int hp);

private:

    int hp;
};

int main()
{
    Enemy enemy;

    enemy.SetHP(150);

    return 0;
}

void Enemy::SetHP(const int hp)
{
    this->hp = hp;
}

これでエラーは無くなりました。

しかし、Visual Studio Community 2015から警告レベルを4に上げていると↓のメッセージが出るようになりました。

 warning C4458: 'hp' を宣言すると、クラス メンバーが隠蔽されます
 note: 'Enemy::hp' の宣言を確認してください

メンバ変数と引数に同じ名前を付けると警告が出ます。

そのため本編では、メンバ変数には「 m_ 」と言うプリフィックス(接頭辞)を付ける事にしました。


もう1つ、コピーコンストラクタのところで出てきた問題点の対応を書きます。

元となるプログラムは↓の通りです。

<sample program col_cpp002-04>

#include <iostream>

class Player {
public:

    Player();

    Player(const Player &source);

    void ShowStatus() const;

private:

    int m_hp;
};

int main()
{
    Player player;

    Player partner(player);

    partner.ShowStatus();

    return 0;
}

Player::Player() : m_hp(150)
{

}

Player::Player(const Player &source)
{
    std::cout << "自作のコピーコンストラクタ" << std::endl;

    m_hp = source.m_hp;
}

void Player::ShowStatus() const
{
    std::cout << "HP = " << m_hp << std::endl;
}

<実行結果>

自作のコピーコンストラクタ
HP = 150
続行するには何かキーを押してください・・・

コピーコンストラクタを自作した状態です。

メンバ変数は1つしかないので、

m_hp = source.m_hp;

元のデータをコピーして終わっていますが、メンバ変数の数が多くなると行数も多くなります。

そこで「thisポインタ」の出番です。

クラスのポインタですから「*」を付ければ間接的に中身を扱えます。

上のコピーコンストラクタを、

Player::Player(const Player &source)
{
    std::cout << "自作のコピーコンストラクタ" << std::endl;

    *this = source;
}

このように書き換えれば、メンバ変数が大量にあっても一度にコピー出来ます。

クラスは構造体と同じですから、基本的には「=演算子」で代入が可能です。


ブラウザの戻るボタンで戻ってください。