授業を聞いててふと思いついた。
その授業では、モジュールの隠ぺい(オブジェクトのprivateとか)について説明していたんだけど、C++ではprivateにしても外からいじれるという話をどこかで聞いたので試したくなった。
そのオブジェクト自身が漏らす場合
class Player {
int money;
public:
Player(int m) : money(m) { }
int getMoney() { return money; }
int* wrongMethod() { return &money; }
};
int main(){
Player player(10);
cout << player.getMoney() << endl; //=> 10
int* money = player.wrongMethod();
*money *= 100;
cout << player.getMoney() << endl; //=> 1000
return 0;
}
何かのミスで、privateのメンバ変数のアドレスを漏らしてしまった場合。これはほかの言語でもありうるだろう外から位置を特定して触る方法
class Player {
public:
int power;
private:
int HP;
int MP;
int money;
public:
Player(int m) : money(m) {
cout << &power << endl;
cout << &HP << endl;
cout << &MP << endl;
cout << &money << endl;
}
int getMoney() { return money; }
};
int main(){
Player player(10);
cout << &player << endl;
cout << player.getMoney() << endl; //=> 10
int* money = (int*)&player + 3;
*money *= 100;
cout << player.getMoney() << endl; //=> 1000
return 0;
}
Playerのコンストラクタでメンバのアドレスを調べたら、playerのアドレスがpowerと一致していて、また、power、HP、MP、moneyの順でアドレスが4(=sizeof(int))ずつ増えていったのでもしやと思い、playerのアドレスに+3したら見事にアクセスできたwC++のポインタが理解しにくいといわれてるのは、クラスなどの先進的な機能とポインタなどのプリミティブな機能が同居しているところにあるってどっかで見たけど、まさにその通りだとこれで実感した。こういうキケンなことができることは、速度とのトレードオフだろうけど。
おまけ
privateメソッドは内部から漏れることぐらいしか思いつかなかったclass Player {
void privateMethod(){
cout << "@privateMethod" << endl;
}
public:
void (Player::*wrongMethod())() { return &Player::privateMethod; }
};
int main(){
Player player;
(player.*(player.wrongMethod()))();
return 0;
}
関数ポインタの書き方わからんwww