ホームに戻る
出典 :
関連 :
目次 :
クラス(class)と構造体(struct)の差異
C++がCのスーパーセットとして発祥したことから、C++における構造体がCと同様に「変数のみを定義できる」という誤解も多いが、
実際は 構造体にもメンバ関数(メソッド)を定義できる 。
つまりC++においては、 デフォルトのアクセス指定を除き、クラスと構造体の実装は変わらない 。
- クラス : デフォルトのアクセス指定が private
- 構造体 : デフォルトのアクセス指定が public
CとC++での構造体の差異
反面、CとC++では構造体の実装に微妙な差異がある。
C
構造体定義の際には struct キーワードに続いて「タグ」を指定できる(型定義を同時に行う場合は省略可能)。
「型名」を定義する際は typedef が必要。
// 構造体を定義後、別名を割り当てる
struct tagSt_Hoge1 //< tagSt_Hoge1 はタグであり、型名ではない
{
U1 m_u1_Val;
};
typedef struct tagSt_Hoge1 St_Hoge1; //< タグから型名を定義
// 構造体と別名を同時に定義する
typedef struct tagSt_Hoge2 //< タグ tagSt_Hoge2 は省略可能
{
U1 m_u1_Val;
} St_Hoge2;
// タグを用いた変数宣言 (struct キーワードが必要)
struct tagSt_Hoge1 g_st_Hoge1_1;
struct tagSt_Hoge2 g_st_Hoge2_1;
// typedef で定義した型名を用いた変数宣言
St_Hoge1 g_st_Hoge1_2;
St_Hoge2 g_st_Hoge2_2;
C++
C++における「構造体定義」は「構造体型定義」を兼ねる(「タグ」が「正式な型名」となる)ため、型定義に typedef を必要としない。
(C同様 typedef (または using )で別名を付与できるが、単に冗長であるだけでなく、二重管理となり混乱を生じる可能性がある。)
// クラス定義
class C_Hoge0 //< クラス型 C_Hoge0
{
U1 m_u1_Val; //< デフォルトは private
public:
C_Hoge0() {}
GetVal() const { return m_u1_Val; }
};
// 構造体定義
struct St_Hoge1 //< St_Hoge1 は正規の構造体型名(タグではない)
{
St_Hoge1() {} //< デフォルトは public
GetVal() const { return m_u1_Val; } //< ↑
private:
U1 m_u1_Val;
};
// 変数宣言
C_Hoge0 g_cl_Hoge0; //< クラス
St_Hoge1 g_st_Hoge1; //< 構造体
どちらを用いるべきか
クラスと構造体では前述したとおり、(デフォルトの)アクセス指定以外の差異は存在しない。
関数(メソッド)を含むオブジェクトはクラスを用いるのが一般的であるが、データのみで構成されるオブジェクトの取り扱いは見解が分かれるため、
クラスと構造体のいずれを用いるかはチームとして方針を定めておくことが望ましい。
尚、クラスと構造体のいずれを用いる場合でも、アクセス指定は明示的に行う(デフォルトを使用しない)ことで混乱を防止できる。
関数の引数や戻り値となるDTO(Data Transfer Object : データ転送オブジェクト)として(関数を含まない)構造体を用いることは一般的だが、
引数や戻り値には構造体ではなくタプルを用いることで、型定義を省略できる。
特に使用頻度が少ない場合や、オブジェクトの寿命が短い場合に有効である。
余談
C++では構造体と同様、共用体にもコンストラクタ・デストラクタを定義できる。
C#ではクラスと構造体の実装は異なり、クラスは参照渡し、構造体は値渡しとなる。詳細は割愛。