C++ ではどのような場合にクラスと構造体を使用する必要がありますか?
質問
どのようなシナリオで使用するのが良いですか struct
対 class
C++で?
解決
の違い class
そして struct
C++では、構造体にはデフォルトがあります public
メンバー、ベース、クラスにはデフォルトがあります private
メンバーも拠点も。クラスと構造体の両方に次のものを混在させることができます。 public
, protected
そして private
メンバーは継承を使用でき、メンバー関数を持つことができます。
構造体をクラスのような機能を持たないプレーンなデータ構造として使用し、クラスを集合データ構造として使用することをお勧めします。 private
データ関数とメンバー関数。
他のヒント
他の人も気づいているように、実際の言語の違いは 2 つだけです。
struct
デフォルトではパブリックアクセスになっており、class
デフォルトではプライベートアクセスになります。- 相続する際には、
struct
デフォルトはpublic
相続とclass
デフォルトはprivate
継承。(皮肉なことに、C++ の多くの機能と同様に、デフォルトは逆方向です。public
継承ははるかに一般的な選択ですが、宣言する人はほとんどいませんstruct
「」を入力する手間を省くためです。public
」というキーワード。
しかし、実際の実際の違いは、 class
/struct
コンストラクター/デストラクターを宣言するものと、そうでないもの。「plain-old-data」POD タイプには特定の保証がありますが、クラスの構築を引き継ぐと、それは適用されなくなります。この区別を明確にするために、多くの人は意図的に のみを使用します。 struct
POD タイプの場合は s を使用し、メソッドを追加する場合は、使用します。 class
エス。それ以外の場合、以下の 2 つのフラグメントの違いは無意味です。
class X
{
public:
// ...
};
struct X
{
// ...
};
(ちなみに、「POD タイプ」の実際の意味については、次のスレッドに詳しい説明があります。 C++ の POD タイプとは何ですか?)
既存の回答には多くの誤解があります。
両方 class
そして struct
クラスを宣言します。
はい、クラスの宣言に使用したキーワードに応じて、クラス定義内のアクセス変更キーワードを再配置する必要がある場合があります。
しかし、構文を超えて、 のみ どちらかを選択する理由は、慣習/スタイル/好みです。
に固執するのが好きな人もいます 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:
構造体のメンバーと基本クラスはデフォルトでパブリックですが、クラスではデフォルトでプライベートになります。注記:デフォルトに依存するのではなく、基本クラスを明示的にパブリック、プライベート、または保護する必要があります。
それ以外の点では、struct と class は機能的に同等です。
さて、きしむようなクリーンなテクノの話はもう終わりました。感情的には、ほとんどの開発者はクラスと構造体を明確に区別します。構造体は単純に、カプセル化や機能性がほとんどない、開いたビットの山のように感じられます。クラスは、インテリジェントなサービス、強力なカプセル化バリア、および明確に定義されたインターフェイスを備えた、生きていて責任ある社会のメンバーであるかのように感じられます。これはほとんどの人がすでに持っている意味なので、メソッドがほとんどなく、公開データを持つクラス (適切に設計されたシステムにはそのようなものは存在します!) があるクラスの場合は、おそらく 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++ で「struct」を使用できますが、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++ コードを使用して C++ ファイルに関数 bar() を記述し、それを 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++ の場合、構造体とクラスの間には大きな違いはありません。主な機能の違いは、構造体のメンバーはデフォルトでパブリックであるのに対し、クラスではデフォルトでプライベートであることです。それ以外の場合、言語に関する限り、それらは同等です。
そうは言っても、ブライアンが言ったことと同様に、私は C# と同じように C++ でも構造体を使用する傾向があります。構造体は単純なデータ コンテナですが、クラスはデータを保持するだけでなくデータに作用する必要があるオブジェクトに使用されます。
私自身の質問に(恥知らずに)答えると、すでに述べたように、C++ におけるそれらの違いはアクセス権限だけです。
私は構造体をデータストレージのみに使用する傾向があります。データの操作が容易になる場合は、いくつかのヘルパー関数を取得できるようにします。ただし、データにフロー制御が必要になるとすぐに (つまり、内部状態を維持または保護するゲッター/セッター)、または主要な機能 (基本的にはオブジェクトに似た) の取得を開始すると、意図をより適切に伝達するためにクラスに「アップグレード」されます。
それらはほぼ同じものです。C++ の魔法のおかげで、構造体はクラスと同じように関数を保持したり、継承を使用したり、「new」を使用して作成したりすることができます。
唯一の機能上の違いは、クラスはプライベート アクセス権で始まるのに対し、構造体はパブリック アクセス権で始まることです。これは、C との下位互換性を維持するためです。
実際には、私は常に構造体をデータホルダーとして使用し、クラスをオブジェクトとして使用してきました。
クラス。
クラスのメンバーはデフォルトではプライベートです。
class test_one {
int main_one();
};
と同等です
class test_one {
private:
int main_one();
};
それで試してみると
int two = one.main_one();
エラーが発生します: main_one is private
アクセスできないからです。それを初期化することで解決できます。
class test_one {
public:
int main_one();
};
構造体。
構造体は、メンバーがデフォルトでパブリックであるクラスです。
struct test_one {
int main_one;
};
手段 main_one
プライベートです、すなわち
class test_one {
public:
int main_one;
};
私は、メンバーがあらゆる価値を取ることができるデータ構造に構造体を使用しますが、そのようにしやすいです。
これらはデフォルトが異なるだけで同じものです (デフォルトではプライベートです) class
, 、デフォルトではパブリック struct
)、理論的には完全に互換性があります。
そのため、移動するための情報をパッケージ化したいだけの場合は、メソッドをいくつか (多くはありませんが) 配置したとしても、構造体を使用します。それがほとんど不透明なもので、主な使用がデータメンバーに直接ではなくメソッド経由である場合、私は完全なクラスを使用します。
デフォルトでは、構造体にはパブリック アクセスがあり、クラスにはデフォルトでプライベート アクセスがあります。
個人的には、データ転送オブジェクトまたは値オブジェクトとして構造体を使用します。このように使用する場合は、他のコードによる変更を防ぐために、すべてのメンバーを const として宣言します。
の利点 struct
以上 class
それは、「最初にパブリックメンバー、次にプライベートメンバー」に従う場合、コードを 1 行節約できることです。そう考えるとキーワードが見えてきます class
使い物にならない。
のみを使用するもう1つの理由は次のとおりです struct
そして決して class
. 。C++ の一部のコード スタイル ガイドラインでは、関数マクロに小さな文字を使用することを推奨しています。その根拠は、マクロがインライン関数に変換されるときに名前を変更する必要がないということです。こっちも一緒。素晴らしい C スタイルの構造体を持っていると、ある日、コンストラクターまたは便利なメソッドを追加する必要があることがわかりました。に変更しますか? class
?どこにでも?
区別する struct
砂 class
es は面倒すぎて、私たちがやるべきこと、つまりプログラミングを行う邪魔になります。C++ の多くの問題と同様、この問題は下位互換性に対する強い要望から生じます。
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...() メソッドで構造体 Student を返しています。お楽しみください。
C ++でクラスを使用するのはいつですか?
私が使う 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; }
};
POD タイプまたはファンクターを作成する必要がある場合は、構造体を使用します。
すべてのクラス メンバーはデフォルトでプライベートであり、すべての構造体メンバーはデフォルトでパブリックです。クラスにはデフォルトのプライベートベースがあり、Struct にはデフォルトのパブリックベースがあります。C の場合、構造体にはメンバー関数を含めることはできませんが、C++ の場合と同様に、構造体にメンバー関数を追加できます。これらの違い以外には、驚くべきことは何も見つかりません。
他の人が指摘したように
- デフォルトの可視性を除けば、どちらも同等です
- 何らかの理由でどちらか一方を使用せざるを得なくなる理由があるかもしれない
Stroustrup/Sutter から、いつどちらを使用するかについて明確な推奨事項があります。
ただし、sth を前方宣言するのは賢明ではないことに注意してください。クラスとして (class X;
) として定義し、struct (struct X { ... }
)。一部のリンカー (g++ など) では機能する場合もあれば、他のリンカー (MSVC など) では失敗する場合もあるため、開発者は地獄に陥ることになります。
私が struct を使用するのは、関連付けられたメンバー関数を持たないデータを保持し (メンバー データを操作するため)、データ変数に直接アクセスする必要がある場合のみです。
例えば:ファイルやソケットストリームなどからのデータの読み取り/書き込み。関数の引数が多すぎて関数の構文が長すぎる構造体に関数の引数を渡す。
技術的には、デフォルトのアクセシビリティを除いて、クラスと構造の間に大きな違いはありません。さらに、それをどのように使用するかはプログラミングスタイルによって異なります。
私は、Structs はデータ構造 (複数データ型の情報配列など) として意図されており、クラスはコード パッケージ化 (サブルーチンや関数のコレクションなど) として意図されていると考えていました。
:(
私は C++ では「struct」を決して使いません。
意図的に混乱させようとしていない限り、プライベート メンバーが必要なときに構造体を使用するシナリオは想像できません。
構造体を使用することは、データがどのように使用されるかを構文的に示すことのようですが、むしろクラスを作成し、クラス名またはコメントを通じてそれを明示的に示したいと思います。
例えば。
class PublicInputData {
//data members
};