C ++でstruct
aとa を使用した方が良いシナリオは何class
ですか?
C ++でstruct
aとa を使用した方が良いシナリオは何class
ですか?
回答:
C ++のa class
とaの違いstruct
は、構造体にはデフォルトのpublic
メンバーとベースがあり、クラスとクラスにはデフォルトのprivate
メンバーとベースがあることです。クラスと構造体の両方にpublic
、protected
とprivate
メンバーを混在させることができ、継承を使用でき、メンバー関数を持つことができます。
クラスのような機能のないプレーンな古いデータ構造として構造体を使用し、private
データおよびメンバー関数を含む集合データ構造としてクラスを使用することをお勧めします。
他の誰もが指摘するように、実際の言語の違いは実際には2つだけです。
struct
デフォルトはパブリックアクセスで、class
デフォルトはプライベートアクセスです。struct
デフォルトはpublic
継承、class
デフォルトはprivate
継承です。(皮肉なことに、C ++での多くのことと同様に、デフォルトは逆方向です。public
継承がはるかに一般的な選択ですがstruct
、「public
」キーワードの入力を節約するためだけにsを宣言することはほとんどありません。ただし、実際の違いは、コンストラクタ/デストラクタを宣言するclass
/ struct
と宣言しない/の違いです。「plain-old-data」PODタイプには特定の保証があり、クラスの構造を引き継ぐと適用されなくなります。この区別を明確にするために、多くの人は故意struct
にPODタイプにのみsを使用し、メソッドを追加する場合はclass
esを使用します。以下の2つのフラグメントの違いは、それ以外では意味がありません。
class X
{
public:
// ...
};
struct X
{
// ...
};
(ちなみに、ここにある「PODタイプ」が実際に何を意味するかについていくつかの良い説明があるスレッドがあります:C ++のPODタイプとは何ですか?)
struct
、またはclass
あなたのオブジェクトがPODであるかどうかには関係ありませんか、コピーコンストラクタ/デストラクタを定義する必要があるかどうか。メンバー関数も、PODであるものには関係ありません。私があなたが書いたものをもう一度読んでいるとき、私はあなたが別のことを示唆していないことを理解しますが、現在の言葉遣いは混乱しています
既存の回答には多くの誤解があります。
はい、クラスの宣言に使用したキーワードによっては、クラス定義内のアクセス変更キーワードを再配置する必要がある場合があります。
ただし、構文を超えて、どちらかを選択する唯一の理由は、規則/スタイル/設定です。
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
。
class foo { public: ... };
持ち、別の翻訳単位がそれを満たしている必要があるとは確信していませんstruct foo { ... };
。不完全な宣言struct foo;
とclass foo;
互換性があるのは理にかなっています。これらはクラス本体を指定しないため、アクセスレイアウトには何も話しません。
Foo
かつBar
、まだ同等/同じタイプです。私は必ず「再宣言するとき」と言って例を挙げました。私は確信して私はUBに人々を誤解ないよ作るための答えでこれを明らかにするだろう、考えてみれば
クラスの代わりに構造体を使用するのは、関数呼び出しで使用する直前にファンクタを宣言し、明確にするために構文を最小限にしたい場合のみです。例えば:
struct Compare { bool operator() { ... } };
std::sort(collection.begin(), collection.end(), Compare());
構造体のメンバーと基本クラスはデフォルトでパブリックですが、クラスではデフォルトでプライベートになります。注:デフォルトに依存するのではなく、基本クラスを明示的にパブリック、プライベート、または保護する必要があります。
その他の点では、構造体とクラスは機能的に同等です。
さて、きしむクリーンなテクノの話はこれで十分だ。感情的には、ほとんどの開発者はクラスと構造体を強く区別します。構造体は、カプセル化や機能の点で非常に小さなビットの山のように感じられます。クラスは、インテリジェントサービス、強力なカプセル化バリア、明確に定義されたインターフェイスを備えた、社会の生きた責任あるメンバーのように感じます。それはほとんどの人がすでに持っている意味合いなので、メソッドがほとんどなく、パブリックデータがあるクラスがある場合は、おそらくstructキーワードを使用する必要があります(適切に設計されたシステムにそのようなものが存在します)。それ以外の場合は、おそらくクラスを使用する必要がありますキーワード。
構造体が私に役立つ1つの場所は、別のシステムから固定形式のメッセージ(たとえば、シリアルポート)を受信するシステムがある場合です。バイトストリームをフィールドを定義する構造体にキャストして、フィールドに簡単にアクセスできます。
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で行うのと同じことですが、メッセージをクラスにデコードする必要があるというオーバーヘッドは、通常、その価値がないことに気づきます。
operator >>
代わりに、書き込みのクラスにprocessMessage
あなたのCになるだろう機能を、++より適切なC ++のような、より少ないC.ように見える
__packed__
構造体を使用し、エンディアン対応のifdef実装を使用する必要があります(エンディアンが外部データソースと反対のマシンで順序を逆にする必要があります)提供しています)。それはきれいではありませんが、私は移植可能な方法で組み込みプラットフォーム上のリモート周辺機器のレジスタをパック/アンパックするために使用しました。
char
型であり、エイリアスは免除されるため、エイリアスはここでは問題になりません。ただし、char*
別のタイプではありますが、まだ問題があります。aを別のタイプにキャストしても、そのアドレスで初期化されている後者のタイプのオブジェクトが実際に存在しなかった場合、UBは存続期間のルールに違反するためです。Afaikは、宛先の型が簡単に構築できる場合でも、メモリを割り当てただけでは、C ++がそのメモリをその型として正式に扱うことを許可するには不十分です。
内部がC ++であるライブラリを作成しているが、APIはCまたは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;}
};
自分の質問に(恥知らずに)答えるには、既に述べたように、C ++でのアクセス権の違いのみです。
構造体はデータストレージのみに使用する傾向があります。データの操作が簡単になる場合は、いくつかのヘルパー関数を取得できるようにします。ただし、データがフロー制御(つまり、内部状態を維持または保護するゲッター/セッター)を必要とするか、主要な機能(基本的にはオブジェクトのようなもの)の取得を開始するとすぐに、意図をより適切に伝達するためにクラスに「アップグレード」されます。
構造体(POD、より一般的には)は、C ++実装を備えたC互換のインターフェースを提供する場合に便利です。それらは言語の境界やリンカー形式を越えて移植できるためです。
それがあなたにとって問題ではないのであれば、「クラス」の代わりに「構造体」を使用することが意図のコミュニケーターであると思います(@ZeroSignalが上で述べたように)。構造体は、より予測可能なコピーセマンティクスも備えているため、外部メディアに書き込んだり、ネットワーク経由で送信したりする予定のデータに役立ちます。
構造体は、依存するtypedefの束を公開するだけの特性テンプレートなど、さまざまなメタプログラミングタスクにも便利です。
template <typename T> struct type_traits {
typedef T type;
typedef T::iterator_type iterator_type;
...
};
...しかし、それは構造体のデフォルトの保護レベルが公開されていることを実際に利用しているだけです...
他の人が指摘したように
Stroustrup / Sutterからwhichをいつ使用するかについての明確な推奨事項があります。
ただし、sthをフォワード宣言するのは賢明ではないことに注意してください。クラス(class X;
)として、それをstruct(struct X { ... }
)として定義します。一部のリンカー(g ++など)では機能し、他のリンカー(MSVCなど)では失敗する可能性があるため、開発者の地獄にいることになります。
class Foo; struct Foo { void bar() {} }; int main() { Foo().bar(); }
ことは、MSVC 2017でコンパイルして実行するだけでなく、Foo
宣言されたstruct
がとして定義された明確な警告を生成しclass
ます。しかし、私はまた、その愚かなバグを見つけるのに半日かかることをはっきり覚えています。当時使用していたMSVCのバージョンがわかりません。
class
struct
struct
-forwardsをclass
-forwards に置き換えると、問題はなくなりました。今日も不思議です。あなたがそれに光を当てることができれば私はうれしいです。
クラスのメンバーはデフォルトでプライベートです。
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;
};
私は、メンバーが任意の値を取ることができるデータ構造に構造体を使用していますが、その方が簡単です。
struct
以上の利点は、class
「最初のパブリックメンバー、次にプライベート」に準拠している場合、コードを1行節約できることです。この観点から、このキーワードはclass
役に立たないと思います。
ここにのみ使用し、使用しない別の理由がstruct
ありclass
ます。C ++の一部のコードスタイルガイドラインでは、関数マクロに小文字を使用することを推奨しています。その理由は、マクロをインライン関数に変換するときに、名前を変更する必要がないためです。こっちも一緒。素敵なCスタイルの構造体があり、ある日、コンストラクタまたは便利なメソッドを追加する必要があることがわかりました。に変更しますclass
か?どこにでも?
struct
sとclass
esを区別するのは、私たちがやるべきこと、つまりプログラミングのやり方にたどり着くのが面倒すぎます。多くのC ++の問題と同様に、それは後方互換性に対する強い欲求から生じます。
class
ですか?struct
キーワードで定義されたクラスはメンバー関数またはコンストラクターを持つことができないと思いましたか?
joe()
で定義する必要がありますclass
か?少なくとも4つのint
メンバーを持つすべてのクラスは、struct
キーワードで定義する必要がありますか?
struct
、メソッド付き集計はclass
」で定義されています。面倒すぎる。
どちらも内部的struct
にclass
は同じstruct
ですが、可視性に関するデフォルトは異なりますが、デフォルトはパブリックであり、class
デフォルトはプライベートです。あなたは、適切な使用と他のようにどちらか一方を変更することができますprivate
し、public
。どちらも継承、メソッド、コンストラクタ、デストラクタ、およびオブジェクト指向言語のその他すべての利点を許可します。
ただし、2つの大きな違いの1つはstruct
、キーワードとしてCではサポートされているのに対し、サポートされてclass
いないことです。1が使用できるこれが意味struct
することができ、インクルードファイルに#include
限り、C ++またはCのいずれかにstruct
プレーンなCのスタイルであるstruct
ファイルを含めるにし、他のすべてがすなわちなどがないC ++固有のキーワード、Cとの互換性がありprivate
、public
いや、メソッド、継承なしなどなど
ACスタイルstruct
は、Cスタイルの使用をサポートする他のインターフェースと併用struct
して、インターフェースを介してデータをやり取りすることができます。
Cスタイルstruct
は、メモリ領域のレイアウトを記述する一種のテンプレート(C ++テンプレートではなく、パターンまたはステンシル)です。長年にわたり、CおよびCプラグイン(ここではJavaとPythonおよびVisual Basicを参照)で使用可能なインターフェースが作成されており、その一部はCスタイルで動作しstruct
ます。
技術的には両方とも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 ...()メソッドで学生構造体を返しています-楽しんでください。
いつstructを使用し、いつC ++で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; }
};
std::binary_function<>
は非推奨ではなく、c ++ 17でも削除されます。
C ++では「構造体」を使用しません。
意図的に混乱させようとしない限り、プライベートメンバーが必要なときに構造体を使用するシナリオを想像することはできません。
構造体を使用することは、データがどのように使用されるかを示す構文的な指示のようですが、クラスを作成し、クラスの名前で、またはコメントを使用してそれを明示的にすることをお勧めします。
例えば
class PublicInputData {
//data members
};
struct
クラスのメンバーがデフォルトでパブリックになることをすでに明示的に宣言しませんか?