クラスには自分自身のアドレスを保持する「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;
}
|
このように書き換えれば、メンバ変数が大量にあっても一度にコピー出来ます。
クラスは構造体と同じですから、基本的には「=演算子」で代入が可能です。
ブラウザの戻るボタンで戻ってください。