Struct と Class
CoddyのC++ジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 37/104。
C++において、structとclassはほぼ同一です。どちらもメンバ変数、メンバ関数、コンストラクタを持つことができ、継承をサポートしています。唯一の違いは、それらのデフォルトのアクセスレベルです。
class内では、メンバーはデフォルトで非公開(private)です。struct内では、メンバーはデフォルトで公開(public)です:
struct Point {
int x; // デフォルトでpublic
int y; // デフォルトでpublic
};
class Circle {
double radius; // デフォルトでprivate
public:
double getRadius() { return radius; }
};これは継承にも当てはまります。structはデフォルトでパブリックに継承しますが、classはプライベートに継承します:
struct DerivedStruct : Base {}; // パブリック継承
class DerivedClass : Base {}; // プライベート継承これらのデフォルト設定を除けば、技術的な違いはありません。しかし、慣習は重要です。
ほとんどのC++プログラマーは、公開メンバを持つ単純なデータコンテナ(座標や設定など)には struct を使用し、カプセル化や振る舞いが重要な場合には class を使用します。この慣習に従うことで、他の開発者に対してコードの意図がより明確になります。
チャレンジ
簡単C++の慣習に基づき、structとclassをいつ使い分けるかを示すシンプルな設定システムを構築しましょう。オープンにアクセスすることを目的としたシンプルなデータにはstructを、カプセル化と制御されたアクセスが必要なデータにはclassを作成します。
コードを整理するために2つのファイルを作成します:
Config.h: 異なる種類の設定データを表す構造体とクラスの両方を定義します。まず、幅と高さ(両方とも
int)を保持するシンプルなデータコンテナであるDimensionsというstructを作成します。構造体はデフォルトでメンバが公開(public)されているため、これらはゲッターなしで直接アクセスできる必要があります。幅と高さの積を返すarea()メソッドを含めてください。次に、適切なカプセル化を行ってアプリケーション設定を管理する
AppConfigというclassを作成します。これには、アプリ名(string)とウィンドウサイズ用のDimensionsオブジェクトを格納する必要があります。クラスのメンバはデフォルトで非公開(private)であるため、公開インターフェースを明示的にアクセス可能にする必要があります。以下を提供してください:- アプリ名、幅、高さを引数に取るコンストラクタ
- 名前を返すゲッター
getAppName() Dimensionsを返すゲッターgetWindowSize()"App: <name>, Window: <width>x<height>, Area: <area>"と出力するdisplayConfig()メソッド
main.cpp: 構造体とクラスの使用法の違いを実演します。入力からアプリ名、幅、高さ(3つの別々の行)を読み取り、以下の処理を行います:- 幅と高さの値を使用して
Dimensions構造体を直接作成し、そのメンバに直接アクセスして"Direct struct access: <width> x <height>"と出力します。 - 3つの値すべてを使用して
AppConfigオブジェクトを作成します。 displayConfig()を呼び出して、完全な設定を表示します。- ゲッターを使用してウィンドウの寸法を取得し、
"Via getter - Area: <area>"と出力します。
- 幅と高さの値を使用して
このチャレンジは、「座標や寸法のようなシンプルで透過的なデータには struct を使い、アクセスを制御しデータに関連する振る舞いを追加したい場合には class を使う」という慣習を強調しています。
std::stoi() を使用して、入力された幅と高さの文字列を整数に変換してください。ヘッダーファイルにはヘッダーガードを忘れずに追加してください。
チートシート
C++において、structとclassはほぼ同一ですが、1つの重要な違いがあります。それは、デフォルトのアクセスレベルです。
structでは、メンバはデフォルトでpublicです:
struct Point {
int x; // デフォルトでpublic
int y; // デフォルトでpublic
};classでは、メンバはデフォルトでprivateです:
class Circle {
double radius; // デフォルトでprivate
public:
double getRadius() { return radius; }
};これは継承にも適用されます:
struct DerivedStruct : Base {}; // デフォルトでpublic継承
class DerivedClass : Base {}; // デフォルトでprivate継承慣習: 公開メンバを持つ単純なデータコンテナにはstructを使用し、カプセル化や振る舞いが重要な場合にはclassを使用します。
自分で試してみよう
#include <iostream>
#include <string>
#include "Config.h"
using namespace std;
int main() {
// 入力を読み込む
string appName;
string widthStr;
string heightStr;
getline(cin, appName);
getline(cin, widthStr);
getline(cin, heightStr);
int width = stoi(widthStr);
int height = stoi(heightStr);
// TODO: width と height を持つ Dimensions 構造体を作成する
// そのメンバに直接アクセスして "Direct struct access: <width> x <height>" と出力する
// TODO: appName、width、height を使用して AppConfig オブジェクトを作成する
// TODO: AppConfig オブジェクトで displayConfig() を呼び出す
// TODO: getWindowSize() ゲッターを使用してディメンションを取得し、"Via getter - Area: <area>" と出力する
return 0;
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
3コンストラクタとデストラクタ
デフォルトコンストラクタ引数付きコンストラクタコピーコンストラクタムーブコンストラクタコンストラクタ初期化リスト委譲コンストラクタデストラクタ詳解Rule of Three / Five / Zeroまとめ - Stringクラス6演算子オーバーロード
演算子オーバーロード入門算術演算子のオーバーロード比較演算子のオーバーロードストリーム演算子代入演算子のオーバーロード[] と () 演算子のオーバーロード型変換演算子まとめ:Matrix クラス