この質問は、C#/.Net のコンテキストで既に尋ねられています。
ここで、C++ の構造体とクラスの違いを学びたいと思います。オブジェクト指向設計でどちらかを選択する理由と同様に、技術的な違いについても説明してください。
明らかな違いから始めます。
public:
またはを指定しない場合private:
、構造体のメンバーは既定でパブリックになります。クラスのメンバーはデフォルトでプライベートです。
C++ 仕様のあいまいな部分に他にも違いがあると確信しています。
クラスと構造体の 2 番目のトリッキーな違いを忘れています。
標準を引用します (C++98 から C++11 までの§11.2.2):
基本クラスにaccess-specifierがない 場合、派生クラスが structと宣言されている場合は public と見なされ、クラスがclassと宣言されている場合は private と見なされます。
完全を期すために、より広く知られているクラスと構造体の違いは (11.2) で定義されています。
キーワードclassで定義されたクラスのメンバーは、デフォルトでプライベートです。キーワードstructまたはunionで定義されたクラスのメンバーは、デフォルト でpublicです。
追加の違い: キーワードclass
はテンプレート パラメーターの宣言に使用できますが、struct
キーワードはそのようには使用できません。
C ++ FAQの引用、
[7.8]キーワードstructとclassの違いは何ですか?
構造体のメンバーと基本クラスはデフォルトでパブリックですが、クラスではデフォルトでプライベートになります。注:デフォルトに依存するのではなく、基本クラスを明示的にパブリック、プライベート、または保護する必要があります。
構造体とクラスは、それ以外は機能的に同等です。
OK、きしむようなクリーンなテクノトークで十分です。感情的には、ほとんどの開発者はクラスと構造体を強く区別しています。構造体は、カプセル化や機能性がほとんどない、ビットの開いた山のように感じます。クラスは、インテリジェントなサービス、強力なカプセル化バリア、および明確に定義されたインターフェイスを備えた、生きた責任ある社会の一員のように感じます。これはほとんどの人がすでに持っている意味なので、メソッドがほとんどなく、公開データがあるクラスがある場合はおそらくstructキーワードを使用する必要があります(そのようなものは適切に設計されたシステムに存在します!)が、そうでない場合はおそらくクラスを使用する必要がありますキーワード。
C++ の起源と C との互換性を覚えておくことは価値があります。
C には構造体があり、カプセル化の概念がないため、すべて公開されています。
デフォルトでパブリックであることは、オブジェクト指向アプローチを採用する場合、一般に悪い考えと見なされます。 C++ (元々は "C With Classes") でのアイデアで、既定でメンバーをプライベートにすることは理にかなっています。
一方、Stroustrup が のセマンティクスを変更しstruct
て、メンバーがデフォルトで非公開になるようにすると、互換性が失われます (標準が分岐するほど頻繁ではなくなりますが、有効な C プログラムはすべて有効な C++ プログラムでもありました。これは、C++ に足がかりを与えるのに大きな影響を与えました)。
class
そのため、構造体とまったく同じように新しいキーワードが導入されましたが、デフォルトではプライベートです。
C++ が履歴なしでゼロから作成された場合、そのようなキーワードはおそらく 1 つしかありません。また、おそらくそれがもたらした影響はなかったでしょう。
一般に、人々は、C で構造体がどのように使用されるかのようなことを行うときに、構造体を使用する傾向があります。パブリックメンバー、コンストラクターなし(共用体でない限り、クラスと同じように構造体にコンストラクターを含めることができますが、人々はそうしない傾向があります)、仮想メソッドなしなど。言語は通信するだけなのでマシンに指示するようにコードを読んでいる人 (または、アセンブリと生の VM オペコードに固執する) に固執することをお勧めします。
クラスのメンバーはデフォルトで非公開です。構造体のメンバーはデフォルトで public です。それ以外に違いはありません。この質問も参照してください。
C++プログラミング言語のStroustrupによると:
どちらのスタイルを使用するかは、状況と好みによって異なります。私は通常、
struct
すべてのデータが公開されているクラスに使用することを好みます。私はそのようなクラスを「適切な型ではなく、単なるデータ構造」と考えています。
機能的には、パブリック/プライベート以外に違いはありません
たとえば、プログラム 1 はコンパイルに失敗し、プログラム 2 は正常に動作します。
// Program 1
#include <stdio.h>
class Test {
int x; // x is private
};
int main()
{
Test t;
t.x = 20; // compiler error because x is private
getchar();
return 0;
}
// Program 2
#include <stdio.h>
struct Test {
int x; // x is public
};
int main()
{
Test t;
t.x = 20; // works fine because x is public
getchar();
return 0;
}
たとえば、プログラム 3 はコンパイルに失敗し、プログラム 4 は正常に動作します。
// Program 3
#include <stdio.h>
class Base {
public:
int x;
};
class Derived : Base { }; // is equivalent to class Derived : private Base {}
int main()
{
Derived d;
d.x = 20; // compiler error because inheritance is private
getchar();
return 0;
}
// Program 4
#include <stdio.h>
class Base {
public:
int x;
};
struct Derived : Base { }; // is equivalent to struct Derived : public Base {}
int main()
{
Derived d;
d.x = 20; // works fine because inheritance is public
getchar();
return 0;
}
STRUCT は、構造の仕様に従ってメモリの特定のチャンクを分割する抽象データ型の一種です。多くの場合、構造体はファイルに逐語的に書き込むことができるため、構造体はファイルのシリアライゼーション/デシリアライゼーションで特に役立ちます。(つまり、構造体へのポインターを取得し、SIZE マクロを使用してコピーするバイト数を計算し、データを構造体の内外に移動します。)
クラスは、情報を確実に隠そうとする別のタイプの抽象データ型です。内部的には、さまざまな機械化、メソッド、一時変数、状態変数が存在する可能性があります。これらはすべて、クラスを使用したいコードに一貫した API を提示するために使用されます。
実際、構造体はデータに関するものであり、クラスはコードに関するものです。
ただし、これらは単なる抽象化であることを理解する必要があります。クラスによく似た構造体や、構造体によく似たクラスを作成することは完全に可能です。実際、初期の C++ コンパイラは、C++ コードを C に変換するプリコンパイラに過ぎませんでした。したがって、これらの抽象化は、論理的思考にとって有益であり、必ずしもコンピューター自体にとっての資産ではありません。
それぞれが異なるタイプの抽象化であるという事実を超えて、クラスは C コードの命名パズルに対する解決策を提供します。複数の関数を同じ名前で公開することはできないため、開発者は _() のパターンに従っていました。例えば、mathlibextreme_max()。API をクラスにグループ化することにより、同様の関数 (ここでは「メソッド」と呼びます) をグループ化して、他のクラスのメソッドの名前付けから保護できます。これにより、プログラマーはコードをより適切に整理し、コードの再利用を増やすことができます。理論的には、少なくとも。
その他の唯一の違いは、クラスと構造体のデフォルトの継承であり、当然のことながら、それぞれプライベートとパブリックです。
class A{
public:
int i;
};
class A2:A{
};
struct A3:A{
};
struct abc{
int i;
};
struct abc2:abc{
};
class abc3:abc{
};
int _tmain(int argc, _TCHAR* argv[])
{
abc2 objabc;
objabc.i = 10;
A3 ob;
ob.i = 10;
//A2 obja; //privately inherited
//obja.i = 10;
//abc3 obss;
//obss.i = 10;
}
これはVS2005にあります。
もう 1 つ注意すべき点として、クラスを使用する構造体を持つレガシー アプリを更新すると、次の問題が発生する可能性があります。
古いコードには構造体があり、コードがクリーンアップされ、これらがクラスに変更されました。その後、新しく更新されたクラスに 1 つまたは 2 つの仮想関数が追加されました。
仮想関数がクラス内にある場合、コンパイラは内部的に関数を指すクラス データへの追加のポインターを追加します。
これが古いレガシー コードをどのように破壊するかというと、古いコードのどこかで構造体が memfill を使用してすべてゼロにクリアされた場合、これにより余分なポインタ データも踏みつぶされます。
もう 1 つの主な違いは、テンプレートに関してです。私の知る限り、テンプレートを定義するときにクラスを使用できますが、構造体は使用できません。
template<class T> // OK
template<struct T> // ERROR, struct not allowed here
仕様にはありません。主な違いは、プログラマーが 2 年後にコードを読むときの期待値です。多くの場合、構造体は POD と見なされます。オブジェクトを定義する以外の目的で型を定義する場合、構造体はテンプレート メタプログラミングでも使用されます。
それは単なる慣習です。構造体は単純なデータを保持するように作成できますが、後でメンバー関数とコンストラクターを追加することで時間を進化させます。一方、パブリック以外のもの、つまり構造体でのアクセスを見るのは珍しいことです。
ここに良い説明があります: http://carcino.gen.nz/tech/cpp/struct_vs_class.php
もう一度言いますが、C++ では、構造体のメンバーはデフォルトでパブリックな可視性を持っていますが、クラスのメンバーはデフォルトでプライベートな可視性を持っていることを除いて、構造体はクラスと同じです。
ISO IEC 14882-2003
9クラス
§3
構造体はclass-key で定義されたクラス
struct
です。そのメンバーと基本クラス (第 10 節) はデフォルトで公開されます (第 11 節)。
他の回答によって暗示されていますが、明示的には言及されていません-使用法に応じて、構造体はCと互換性があります。クラスはそうではありません。
これは、C 互換にしたいヘッダーを書いている場合、構造体 (C の世界では関数を持つことはできませんが、関数ポインターを持つことはできます) 以外のオプションがないことを意味します。
. クラスでは、デフォルトですべてのメンバーがプライベートですが、構造体のメンバーはデフォルトでパブリックです。
構造体にはコンストラクターやデストラクタのような用語はありませんが、クラス コンパイラーは指定しないとデフォルトを作成します。
空の構造体のサイズは 0 バイトです。空のクラスのサイズは 1 バイトです。構造体のデフォルトのアクセス タイプは public です。通常、構造体はデータのグループ化に使用する必要があります。
クラスの既定のアクセス タイプはプライベートであり、継承の既定のモードはプライベートです。クラスは、データとそのデータを操作するメソッドをグループ化するために使用する必要があります。
つまり、データのグループ化が目的の場合は struct を使用し、データの抽象化と、おそらく継承が必要な場合はクラスを使用するという慣習があります。
C++ では、明示的に逆参照しない限り、構造体とクラスは値渡しされます。他の言語では、クラスと構造は異なるセマンティクスを持つ場合があります。オブジェクト (クラスのインスタンス) は参照によって渡され、構造体は値によって渡されます。注: この質問に関連するコメントがあります。会話に追加するには、ディスカッション ページを参照してください。
他の回答では、プライベート/パブリックのデフォルトについて言及しています (ただし、構造体はクラスであり、構造体であることに注意してください。これらは 2 つの異なる項目ではなく、同じ項目を定義する 2 つの方法にすぎません)。
注意すべき興味深い点は (特に、質問者が「管理されていない」C++ について言及しているため、MSVC++ を使用している可能性が高いため)、Visual C++ は、クラスが で宣言されてclass
から で定義されたstruct
場合 (またはその逆の可能性がある場合)、特定の状況下で文句を言うことです。 )、標準では完全に合法であるとされていますが。
構造体またはクラスをいつ使用するかについてのガイドラインとして、これを検討してください ( https://msdn.microsoft.com/en-us/library/ms229017%28v=vs.110%29.aspx )。
√ 型のインスタンスが小さく、一般的に短命である場合、または一般的に他のオブジェクトに埋め込まれている場合は、クラスの代わりに構造体を定義することを検討してください。
X 型が次の特性をすべて備えていない限り、構造体を定義することは避けてください。
プリミティブ型 (int、double など) と同様に、単一の値を論理的に表します。
インスタンス サイズは 16 バイト未満です。
不変です。
頻繁に箱詰めする必要はありません。
クラスは、ソフトウェア エンジニアリングのコンテキストでのみ意味があります。データ構造とアルゴリズムのコンテキストでは、クラスと構造体はそれほど違いはありません。クラスのメンバーを参照する必要があるという制限はありません。
クラスのない大勢の人々が参加する大規模なプロジェクトを開発する場合、最終的には複雑な結合コードになる可能性があります。クラスは、コードの分離と再利用を強化するための許可制御と固有のものを提供します。
ソフトウェア エンジニアリングの原則をいくつか読むと、ほとんどの標準はクラスなしでは簡単に実装できないことがわかります。例: http://en.wikipedia.org/wiki/SOLID_%28object-directional_design%29
ところで、構造体がメモリのクランチを割り当て、いくつかの変数が含まれている場合、値型変数は、構造体が割り当てられている場所に値が埋め込まれていることを示します。対照的に、参照型変数の値は外部であり、構造体が割り当てられている場所にも埋め込まれているポインターによって参照されます。
C++ のstructキーワードとclassキーワードの違いは、特定の複合データ型に特定の指定子がない場合、デフォルトでstructまたはunionは単にデータの隠蔽を考慮するパブリック キーワードですが、class はプログラムの隠蔽を考慮するプライベート キーワードです。コードまたはデータ。常に一部のプログラマーは、コードのためにデータとクラスに構造体を使用します。詳細については、他のソースにお問い合わせください。
**更新: ** この返信は無視してください。構造体の場合、値が初期化されていない可能性を考慮していませんでしたが、たまたま 0 でした。構造体とクラスの間に初期化の違いはありません。
デフォルトの初期化に関係する構造体とクラスの間で別の違いが見られます。
struct Foo {
int a;
};
class Bar {
int a;
};
class Tester {
Foo m_Foo = Foo();
Bar m_Bar = Bar();
public:
Tester() {}
};
int main() {
auto myTester = Tester();
}
そのコードを実行し、myTester を調べます。m_Foo の構造体 m_Foo.a は 0 に初期化されていますが、m_Bar のクラス m_Bar.a は初期化されていません。したがって、構造体とクラスに対してデフォルトのコンストラクターが行うことには違いがあるようです。私はこれを Visual Studio で見ています。
私は他の違いを見つけました。クラスでコンストラクターを定義しない場合、コンパイラーがコンストラクターを定義します。ただし、コンストラクターを定義しない場合の構造体では、コンパイラーもコンストラクターを定義しません。したがって、コンストラクターが本当に必要ない場合は、structの方が適しています(パフォーマンスのヒント)。英語が下手でごめんなさい。
構造とクラスには3つの基本的な違いがあります
1st- メモリはスタック メモリ (プログラミング言語に近い) 内の構造用に予約されています。
2nd - デフォルトでは、クラスがプライベートとして扱われるかどうかにかかわらず、構造はパブリックとして扱われます。
3Rd- 構造内でコードを再利用することはできませんが、クラスでは継承と呼ばれる同じコードを何度も再利用できます