C++ でstruct
a と aを使用する方がよいシナリオはどれですか?class
27 に答える
C++ での aclass
と aの違いは次のとおりです。struct
struct
メンバーと基本クラス/構造体はpublic
デフォルトです。class
メンバーと基本クラス/ストラットはprivate
デフォルトです。
public
クラスと構造体の両方に、protected
とメンバーを混在させることがprivate
でき、継承を使用でき、メンバー関数を持つことができます。
私はあなたをお勧めします:
struct
クラスのような機能を持たない単純な古いデータ構造に使用します。- またはメンバー、デフォルト以外のコンストラクターや演算子などの機能を利用する
class
ときに使用します。private
protected
他の誰もが指摘しているように、実際には実際の言語の違いは 2 つだけです。
struct
デフォルトはパブリック アクセス、class
デフォルトはプライベート アクセスです。- 継承する場合は、
struct
デフォルトでpublic
継承され、class
デフォルトでprivate
継承されます。(皮肉なことに、C++ の非常に多くのことと同様に、デフォルトは逆です。public
継承ははるかに一般的な選択ですが、" " キーワードstruct
の入力を節約するためだけに s を宣言することはめったにありません。public
しかし、実際の違いは、コンストラクタ/デストラクタを宣言する / と宣言しないclass
/の間です。struct
「plain-old-data」POD タイプには一定の保証があり、クラスの構築を引き継ぐと適用されなくなります。この区別を明確にするために、多くの人は意図的struct
に POD タイプにのみ s を使用し、メソッドを追加する場合はclass
es を使用します。以下の 2 つのフラグメントの違いは、それ以外の場合は意味がありません。
class X
{
public:
// ...
};
struct X
{
// ...
};
(ちなみに、「POD 型」が実際に何を意味するかについて、いくつかの適切な説明が記載されたスレッドがあります: What are POD types in C++? )
既存の回答には多くの誤解があります。
はい、クラスの宣言に使用したキーワードに応じて、クラス定義内のアクセス変更キーワードを再配置する必要がある場合があります。
しかし、構文を超えて、どちらかを選択する唯一の理由は、規則/スタイル/設定です。
struct
結果として得られる定義が C の単純な構造に「似ている」ため、メンバー関数を持たないクラスのキーワードに固執することを好む人もいます。
class
同様に、メンバー関数とデータを持つクラスにキーワードを使用することを好む人もいprivate
ます。これは、「クラス」と表示されているため、オブジェクト指向プログラミングに関するお気に入りの本の例のように見えるからです。
現実には、これは完全にあなたとあなたのチーム次第であり、あなたのプログラムには文字通り何の違いもありません。
次の 2 つのクラスは、名前を除いてすべての点で完全に同等です。
struct Foo
{
int x;
};
class Bar
{
public:
int x;
};
再宣言時にキーワードを切り替えることもできます:
class Foo;
struct Bar;
(ただし、これは非準拠のためにVisual Studio のビルドを中断するため、これを行うとコンパイラは警告を発します。)
また、次の式は両方とも true と評価されます。
std::is_class<Foo>::value
std::is_class<Bar>::value
ただし、再定義するときにキーワードを切り替えることはできないことに注意してください。これは、(1 つの定義のルールに従って) 翻訳単位全体で重複するクラス定義が「同じトークンのシーケンスで構成される」必要があるためです。const int member;
これは、 と交換することさえできず、またはint const member;
のセマンティクスとは何の関係もないことを意味します。class
struct
クラスの代わりに構造体を使用するのは、関数呼び出しで使用する直前にファンクターを宣言し、わかりやすくするために構文を最小限に抑えたい場合だけです。例えば:
struct Compare { bool operator() { ... } };
std::sort(collection.begin(), collection.end(), Compare());
C++ FAQ Liteから:
構造体のメンバーと基本クラスは既定でパブリックですが、クラスでは既定でプライベートになります。注: デフォルトに依存するのではなく、基底クラスを明示的に public、private、または protected にする必要があります。
それ以外の場合、構造体とクラスは機能的に同等です。
OK、きしむようなクリーンなテクノトークはもう十分だ。感情的には、ほとんどの開発者はクラスと構造体を明確に区別しています。構造体は、カプセル化や機能がほとんどないビットの開いた山のように単純に感じられます。クラスは、インテリジェントなサービス、強力なカプセル化バリア、および明確に定義されたインターフェイスを備えた、社会の生きた責任あるメンバーのように感じられます。これはほとんどの人がすでに持っている意味合いであるため、メソッドがほとんどなく公開データを持つクラスがある場合は、おそらく struct キーワードを使用する必要があります (そのようなものは、適切に設計されたシステムに存在します!)。それ以外の場合は、おそらくクラスを使用する必要がありますキーワード。
構造体が役に立ったのは、別のシステムから固定形式のメッセージ (たとえば、シリアル ポート経由) を受信しているシステムがある場合です。バイト ストリームをフィールドを定義する構造体にキャストして、フィールドに簡単にアクセスできます。
typedef struct
{
int messageId;
int messageCounter;
int messageData;
} tMessageType;
void processMessage(unsigned char *rawMessage)
{
tMessageType *messageFields = (tMessageType *)rawMessage;
printf("MessageId is %d\n", messageFields->messageId);
}
明らかに、これは C で行うのと同じことですが、メッセージをクラスにデコードする必要があるというオーバーヘッドは、通常は価値がないことがわかりました。
内部が C++ であるライブラリを作成している場合、C++ で「構造体」を使用できますが、API は C または C++ コードで呼び出すことができます。次のように、C と C++ コードの両方に公開する構造体とグローバル API 関数を含む単一のヘッダーを作成するだけです。
// C access Header to a C++ library
#ifdef __cpp
extern "C" {
#endif
// Put your C struct's here
struct foo
{
...
};
// NOTE: the typedef is used because C does not automatically generate
// a typedef with the same name as a struct like C++.
typedef struct foo foo;
// Put your C API functions here
void bar(foo *fun);
#ifdef __cpp
}
#endif
次に、C++ コードを使用して関数 bar() を C++ ファイルに記述し、C から呼び出すことができるようにします。2 つの世界は、宣言された構造体を通じてデータを共有できます。もちろん、C と C++ を混在させる場合には他にも注意事項がありますが、これは単純化された例です。
誰もが言うように、唯一の本当の違いはデフォルト アクセスです。しかし、ヘルパー メソッドを実装したとしても、単純なデータ クラスでカプセル化する必要がない場合は、特に struct を使用します。たとえば、次のようなものが必要な場合:
struct myvec {
int x;
int y;
int z;
int length() {return x+y+z;}
};
構造体 ( POD、より一般的には) は、言語の境界やリンカー形式を超えて移植できるため、C++ 実装で C 互換のインターフェイスを提供する場合に便利です。
それが問題にならない場合は、「クラス」の代わりに「構造体」を使用することが意図の良い伝達者であると思います(@ZeroSignalが上記で述べたように)。構造体は、より予測可能なコピー セマンティクスも備えているため、外部メディアに書き込んだり、ネットワーク経由で送信したりするデータに役立ちます。
構造体は、さまざまなメタプログラミング タスクにも便利です。たとえば、依存する typedef の束を公開する特性テンプレートなどです。
template <typename T> struct type_traits {
typedef T type;
typedef T::iterator_type iterator_type;
...
};
...しかし、それは構造体のデフォルトの保護レベルが公開されていることを利用しているだけです...
C++ の場合、構造体とクラスの間に大きな違いはありません。主な機能上の違いは、構造体のメンバーがデフォルトでパブリックであるのに対し、クラスではデフォルトでプライベートであることです。それ以外の場合、言語に関する限り、それらは同等です。
そうは言っても、Brian が言ったことと同様に、C# と同じように C++ でも構造体を使用する傾向があります。構造体は単純なデータ コンテナーですが、クラスはデータを保持するだけでなく、データに基づいて動作する必要があるオブジェクトに使用されます。
私自身の質問に(恥知らずに)答えるために、すでに述べたように、アクセス権限はC ++での唯一の違いです。
私は構造体をデータストレージのみに使用する傾向があります。データの操作が簡単になる場合は、いくつかのヘルパー関数を取得できるようにします。ただし、データがフロー制御 (つまり、内部状態を維持または保護するゲッター/セッター) を必要とするか、主要な機能 (基本的にはよりオブジェクトに似たもの) を取得し始めるとすぐに、意図をより適切に伝達するためにクラスに「アップグレード」されます。
他の人が指摘しているように
- デフォルトの可視性を除けば、どちらも同等です
- 何らかの理由でどちらか一方を使用せざるを得ない理由があるかもしれません
Stroustrup/Sutter から、いつ使用するかについて明確な推奨事項があります。
クラスに不変式がある場合は class を使用します。データ メンバーが独立して変化する可能性がある場合は、構造体を使用します
ただし、sth を前方宣言するのは賢明ではないことに注意してください。クラス ( class X;
) として定義し、構造体 ( struct X { ... }
) として定義します。一部のリンカ (g++ など) では動作するかもしれませんが、他のリンカ (MSVC など) では失敗するかもしれません。
それらはほとんど同じものです。C++ の魔法のおかげで、構造体はクラスと同じように関数を保持したり、継承を使用したり、"new" を使用して作成したりできます。
唯一の機能上の違いは、クラスがプライベート アクセス権で始まるのに対し、構造体はパブリックで始まることです。これにより、C との下位互換性が維持されます。
実際には、私は常に構造体をデータ ホルダーとして使用し、クラスをオブジェクトとして使用してきました。
struct
overの利点はclass
、「最初にパブリック メンバー、次にプライベート」に準拠している場合、1 行のコードを節約できることです。この観点から、このキーワードはclass
役に立たないと思います。
struct
onlyと neverを使用するもう 1 つの理由を次に示しclass
ます。C++ のコード スタイル ガイドラインの中には、関数マクロに小文字を使用することを推奨しているものがあります。これは、マクロをインライン関数に変換するときに名前を変更する必要がないという根拠によるものです。こっちも一緒。素敵な C スタイルの構造体があり、ある日、コンストラクターまたは何らかの便利なメソッドを追加する必要があることがわかりました。に変更しますclass
か?どこにでも?
struct
s とes を区別するのclass
は面倒すぎて、やるべきこと、つまりプログラミングの邪魔になります。多くの C++ の問題と同様に、これは後方互換性に対する強い欲求から生じます。
それらは異なるデフォルト (デフォルトではプライベート、デフォルトでclass
はパブリックstruct
) を持つ同じものであるため、理論的には完全に交換可能です。
したがって、いくつかの情報をパッケージ化して移動したいだけの場合は、そこにいくつかのメソッドを配置したとしても(ただし多くはありません)、構造体を使用します。それがほとんど不透明なものであり、主な使用がメソッドを介して行われ、データメンバーに直接使用されない場合は、完全なクラスを使用します。
デフォルトでは、構造体にはパブリック アクセスがあり、クラスにはデフォルトでプライベート アクセスがあります。
個人的には、データ転送オブジェクトまたは値オブジェクトとして構造体を使用します。そのように使用する場合、他のコードによる変更を防ぐために、すべてのメンバーを const として宣言します。
C ++ 20標準の観点からこれに対処するためだけに(N4860から作業)...
クラスは型です。キーワード " class
" および " struct
" (および " union
") は - C++ 文法では -クラス キーclass
であり、 orの選択の唯一の機能上の意味struct
は次のとおりです。
class-keyは、アクセスがデフォルト (11.9) でパブリックかプライベートかを決定します。
データ メンバーの既定のアクセシビリティ
class
キーワードはデフォルトでプライベート メンバーになり、`struct キーワードはデフォルトでパブリック メンバーになることは、11.9.1 の例で文書化されています。
クラス X { int a; // X::a はデフォルトで非公開です: 使用されるクラス
...対...
構造体 S { int a; // S::a はデフォルトでパブリックです: 使用される構造体
基本クラスのデフォルトのアクセシビリティ
1.9 には次のようにも書かれています。
基本クラスのアクセス指定子がない
public
場合、派生クラスがclass-keystruct
で定義されている場合は と見なされ、クラスがclass-keyprivate
で定義されている場合は と見なされます。class
構造体またはクラスの一貫した使用が必要な状況...
要件があります:
クラステンプレートの再宣言、部分的な特殊化、明示的な特殊化、または明示的なインスタンス化では、クラスキーは元のクラステンプレート宣言と同じように一致するものとします (9.2.8.3)。
...すべての洗練された型指定子では、
enum
キーワードは列挙 (9.7.1) を参照するために使用され、union
クラスキーunion
は(11.5)を参照するために使用され、class
またはstruct
クラスキーは非共用体クラス (11.1) を参照するために使用されます。
次の例 (一貫性が必要ない場合) を示します。
struct S { } s; クラス S* p = &s; // わかった
それでも、一部のコンパイラはこれについて警告する場合があります。
興味深いことに、 、 で作成する型struct
はclass
すべてunion
「クラス」と呼ばれますが、...
標準レイアウト構造体は、 class-key
struct
またはclass -keyで定義された標準レイアウト クラスですclass
。
...標準では、標準レイアウト構造体の話がある場合、 「構造体」を使用して「共用体ではない」ことを暗示しています。
他の用語で「構造体」の同様の使用法があるかどうか興味がありますが、標準を徹底的に検索するには大きすぎます。その歓迎についてのコメント。
POD 型またはファンクターを作成する必要がある場合は、構造体を使用します。
C++ で struct を使用するのはどのような場合で、class を使用するのはどのような場合ですか?
とstruct
を定義するときに使用します。それ以外の場合は を使用します。functors
POD
class
// '()' is public by default!
struct mycompare : public std::binary_function<int, int, bool>
{
bool operator()(int first, int second)
{ return first < second; }
};
class mycompare : public std::binary_function<int, int, bool>
{
public:
bool operator()(int first, int second)
{ return first < second; }
};
技術的には、C++ ではどちらも同じです。たとえば、構造体にオーバーロードされた演算子などを含めることができます。
でも :
複数のタイプの情報を同時に渡したい場合は構造体を使用し、「関数」オブジェクトを扱う場合はクラスを使用します。
それが役に立てば幸い。
#include <string>
#include <map>
using namespace std;
struct student
{
int age;
string name;
map<string, int> grades
};
class ClassRoom
{
typedef map<string, student> student_map;
public :
student getStudentByName(string name) const
{ student_map::const_iterator m_it = students.find(name); return m_it->second; }
private :
student_map students;
};
たとえば、ここの get...() メソッドで構造体の学生を返しています。お楽しみください。
メンバー関数が関連付けられていないデータを保持する必要がある場合 (メンバー データを操作するため)、およびデータ変数に直接アクセスする必要がある場合にのみ、構造体を使用します。
例: ファイルやソケット ストリームなどからのデータの読み取り/書き込み。関数の引数が多すぎて関数の構文が長すぎる構造体で関数の引数を渡す。
技術的には、デフォルトのアクセシビリティを除いて、クラスと構造の間に大きな違いはありません。さらに、それをどのように使用するかは、プログラミングスタイルによって異なります。
Structs はデータ構造 (マルチデータ型の情報の配列など) として意図されており、クラスはコード パッケージ (サブルーチンと関数のコレクションなど) として意図されていると思いました。
:(
C++では「struct」を使用しません。
意図的に混乱させようとしない限り、プライベートメンバーが必要なときに構造体を使用するシナリオを想像することはできません。
構造体を使用することは、データがどのように使用されるかを構文的に示すもののようですが、私はむしろクラスを作成し、クラスの名前で、またはコメントを通じてそれを明示的にしようとします。
例えば
class PublicInputData {
//data members
};