クラスはどのような時に必要になる、というよりは、使うと便利だから使う、といったところではないでしょうか。
主な目的が生産性を上げることにありますので、クラスで出来ることを構造体と関数だけで実現しようと思えば
記述の面で面倒な部分が多くなるだけで出来ないことはありません。
あまりいい例ではありませんが、例えばプレイヤーの情報が詰まった構造体 PLAYER の処理を行う関数があるとしたら、
PLAYER 構造体を処理する関数だと分かるようにする為に全ての関数の前に Player_ をつけ、第一引数は構造体 PLAYER の
アドレスをとるとします。
struct PLAYER
{
int x, y;
int hp, mp;
};
int Player_Setup( PLAYER *Player, int x, int y, int hp, int mp );
int Player_Move( PLAYER *Player, int x, int y );
int Player_Damage( PLAYER *Player, int point );
int Player_Frame( PLAYER *Player );
int Player_Draw( PLAYER *Player );
~~プログラム部分
PLAYER pc;
Player_Setup( &pc, 0, 100, 100, 40 );
Player_Move( &pc, 100, 200 );
これがクラスを使うと次のようになります。
class PLAYER
{
public:
int Setup( int x, int y, int hp, int mp );
int Move( int x, int y );
int Damage( int point );
int Frame( void );
int Draw( void );
private:
int x, y;
int hp, mp;
};
~~プログラム部分
PLAYER pc;
pc.Setup( 0, 100, 100, 40 );
pc.Move( 100, 200 );
関数に PLAYER 構造体のアドレスを渡す必要もなくなり、関数の前に Player_ を書く必要もありません。
そしてついでにメンバ変数の x, y, hp, mp は privete メンバなので、クラスのメンバ関数外からは
アクセス出来ないようになっています。(このへんは一人でプログラムを組んでいるときはあまり関係ありませんが・・・)
C++ やクラスの本領が発揮されるのはクラスの継承だとか、例外処理だとか、演算子のオーバーロードなどと
言った部分ですが、それらも C言語でもやろうと思えば似たようなことが出来ます。
ただ、上記の例も分かる通り、記述の面倒さが軽減します。上記の例では割と 構造体+関数で出来ることをそのまま
クラスに置き換えただけなのでクラスにする必要性を強く感じるものではありませんが、継承や演算子のオーバーロード等の
処理に近いものを構造体+関数で実現しようと思ったときにはその面倒さの軽減=生産性の向上は非常に大きいものです。
で、実用例についてですが、私の周りでは基本的に一つの構造体専用の関数が複数あるような場合は全て構造体
ではなくクラスにしています。(文字列処理クラス、画像処理クラス、ステージクラス、ウインドウクラス、キャラクタクラス等)
キャラクタクラスは継承されてプレイヤークラスや敵クラス(敵クラスは更に継承されてボスクラス、ボスクラスが
更に継承されて各ボスのクラス等)といったような使われ方をしています。
私自身はあんまりクラスを使いこなせていません。orz