web-dev-qa-db-ja.com

C ++の構造体とクラスの違いは何ですか?

この質問は すでにC#/。Net の文脈でなされたものです。

それでは、C++で構造体とクラスの違いを学びたいと思います。 OO designで技術的な違いと、どちらかを選択する理由について説明してください。

明らかな違いから始めます。

  • public:またはprivate:を指定しないと、構造体のメンバーはデフォルトでpublicになります。クラスのメンバーはデフォルトでプライベートです。

C++仕様のあいまいなコーナーには、他にも違いがあるはずです。

414
palm3D

あなたはクラスと構造体の間の難しい2番目の違いを忘れます。

標準を引用しなさい(C++ 98からC++ 11の§11.2.2):

基本クラスにアクセス指定子がない場合、派生クラスが宣言されたときにpublicが想定されますstructクラスがclassと宣言されている場合、privateが想定されます。

そして完全を期すために、クラスと構造体の間でより広く知られている違いは(11.2)で定義されています。

キーワードclassで定義されたクラスのメンバーは、デフォルトでprivateです。キーワードstructまたはunionで定義されたクラスのメンバーはpublicデフォルトではです。

その他の違い:キーワードclassはテンプレートパラメータの宣言に使用できますが、structキーワードはそのようには使用できません。

449
Assaf Lavie

引用 C++ FAQ

[7.8]キーワードstructとclassの違いは何ですか?

構造体のメンバと基本クラスはデフォルトでpublicですが、クラス内ではデフォルトでprivateです。注:デフォルトに頼るのではなく、基本クラスを明示的にpublic、private、またはprotectedにする必要があります。

その他の点では、構造体とクラスは機能的に同等です。

OK、そのきしみのあるクリーンテクノトークは十分にあります。感情的には、ほとんどの開発者はクラスと構造体を大きく区別しています。構造体は、単純にカプセル化や機能性の面でほんの少しのビットの開いた山のように感じます。クラスは、インテリジェントなサービス、強力なカプセル化の障壁、および明確に定義されたインターフェースを備えた、生きて責任を負う社会の一員のように感じます。これはほとんどの人がすでに持っている含意なので、メソッドがほとんどなくパブリックデータを持つクラスがある場合はおそらくstructキーワードを使用するべきですが、そうでなければおそらくクラスを使用するべきですキーワード。

157
Robᵩ

CでのC++の起源と互換性を覚えておく価値はあります。

Cには構造体があり、カプセル化の概念がないため、すべてがパブリックです。

デフォルトでパブリックであることは、オブジェクト指向のアプローチをとる場合、一般に悪い考えと見なされます。そのため、CでネイティブにOOPに役立つフォームを作成する場合、CでOOを実行できます、しかし、それはあなたを助けません)C++(元々は「C With Classes」)のアイデアでしたが、デフォルトでメンバーをプライベートにすることは理にかなっています。

一方、Stroustrupがstructのセマンティクスを変更して、そのメンバーがデフォルトでプライベートになると、互換性が失われます(標準が分岐するほど頻繁ではありませんが、有効なCプログラムはすべてまた、有効なC++プログラムは、C++に足がかりを与えることに大きな効果がありました。

そのため、新しいキーワードclassは、構造体とまったく同じように導入されましたが、デフォルトではプライベートです。

C++がゼロから作成され、履歴がない場合、おそらくそのようなキーワードは1つしかありません。また、おそらくそれがもたらした影響はなかっただろう。

一般に、Cで構造体がどのように使用されるかのようなことをしているとき、人々は構造体を使用する傾向があります。パブリックメンバー、コンストラクタなし(ユニオンにない限り、canクラスと同じように構造体にコンストラクタがありますが、人々はそうではありません)、仮想メソッドなどはありません。言語は、コードを読んでいる人と通信するだけでなく、マシンに指示する(または、アセンブリと生のVMオペコードに固執する)ので、それに固執することをお勧めします。

118
Jon Hanna

クラスのメンバーはデフォルトでプライベートです。 Structのメンバーはデフォルトでパブリックです。それ以外に他の違いはありません。この質問も 見てください

31
Kasprzol

C++プログラミング言語 のStroustrupによると、

どのスタイルを使用するかは状況と好みによって異なります。私は通常、すべてのデータが公開されているクラスにはstructを使用することを好みます。私はそのようなクラスを「まったく適切な型ではなく、単なるデータ構造」と考えています。

機能的には、パブリック/プライベート以外に違いはありません。

28
crashmstr

STRUCTは、構造仕様に従ってメモリの特定のチャンクを分割する抽象データ型の一種です。構造体はファイルに逐語的に書き込むことができることが多いため、構造体はファイルのシリアライゼーション/デシリアライゼーションに特に役立ちます。 (つまり、構造体へのポインタを取得し、SIZEマクロを使用してコピーするバイト数を計算してから、データを構造体の内外に移動します。)

クラスは、情報の隠蔽を確実にすることを試みる異なるタイプの抽象データ型です。内部的には、さまざまな機械化、メソッド、一時変数、状態変数があります。クラスを使用したいコードに一貫したAPIを提示するためにすべて使用されます。

実際には、構造体はデータについて、クラスはコードについてです。

ただし、これらは単なる抽象化であることを理解する必要があります。クラスによく似た構造体や構造体によく似たクラスを作成することは完全に可能です。実際、最も初期のC++コンパイラは、C++コードをCに変換する単なるプリコンパイラでした。したがって、これらの抽象化は論理的思考にとって有益であり、必ずしもコンピュータ自体の資産ではありません。

それぞれが異なる種類の抽象概念であるという事実を超えて、クラスはCコード命名パズルに対する解決策を提供します。同じ名前で複数の関数を公開することはできないため、開発者は以前は_()のパターンに従いました。例えばmathlibextreme_max()。 APIをクラスにグループ化することで、同様の機能(ここではそれらを「メソッド」と呼びます)をまとめて他のクラスのメソッドの命名から保護することができます。これにより、プログラマーは自分のコードをよりよく整理し、コードの再利用を増やすことができます。理論的には、少なくとも。

9
64BitBob

1)クラスのメンバはデフォルトではprivateであり、structのメンバはデフォルトではpublicです。

たとえば、プログラム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;
}
Run on IDE
// 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;
}

2)クラス/構造体から構造体を派生させるとき、基本クラス/構造体のデフォルトのアクセス指定子はpublicです。そしてクラスを派生させるとき、デフォルトのアクセス指定子はprivateです

たとえば、プログラム3はコンパイルに失敗し、プログラム4は正常に動作します。

// Program 3
#include <stdio.h>

class Base {
public:
    int x;
};

class Derived : Base { }; // is equilalent to class Derived : private Base {}

int main()
{
  Derived d;
  d.x = 20; // compiler error becuase inheritance is private
  getchar();
  return 0;
}
Run on IDE
// Program 4
#include <stdio.h>

class Base {
public:
    int x;
};

struct Derived : Base { }; // is equilalent to struct Derived : public Base {}

int main()
{
  Derived d;
  d.x = 20; // works fine becuase inheritance is public
  getchar();
  return 0;
}
9
Suraj K Thomas

他の唯一の違いは、クラスと構造体のデフォルトの継承であり、これは当然のことながらプライベートとパブリックです。

8
Skizz
  1. 構造体のメンバはデフォルトでpublic、クラスのメンバはデフォルトでprivateです。
  2. 他の構造体またはクラスからのStructureのデフォルト継承はpublicです。他の構造体またはクラスからのclassのデフォルト継承はprivateです。
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にあります。

4
GirishNayak

もう1つ注意すべきことは、クラスを使用するための構造体を持つレガシーアプリを更新した場合、次の問題が発生する可能性があります。

古いコードには構造体があり、コードはクリーンアップされ、これらはクラスに変更されました。その後、仮想関数1つまたは2つが新しい更新済みクラスに追加されました。

仮想関数がクラス内にある場合、内部的にコンパイラは関数を指すためにクラスデータへの追加のポインタを追加します。

古いコードのどこかでstructがmemfillを使用してすべてゼロにクリアされた場合、これによって余分なポインターデータも削除されます。

4
KPexEA

仕様ではありません、いいえ。主な違いは、2年間でコードを読むときのプログラマの期待にあります。構造体はしばしばPODと見なされます。オブジェクトの定義以外の目的で型を定義している場合、構造体はテンプレートメタプログラミングでも使用されます。

4
MSalters

もう1つの主な違いは、テンプレートに関することです。私の知る限りでは、テンプレートを定義するときはクラスを使用できますが、構造体は使用できません。

template<class T> // OK
template<struct T> // ERROR, struct not allowed here
3
Stefan Popescu

それは単なる慣例です。単純なデータを保持するために構造体を作成することができますが、後でメンバ関数とコンストラクタを追加することで時間を進化させることができます。一方、public以外のものを見るのは珍しいことです。構造体の中でアクセスすること。

2
finnw

ISO IEC 14882-2003

9つのクラス

§3

構造体は、class-keystruct;で定義されたクラスです。そのメンバーと基底クラス(10章)はデフォルトでは公開されています(11章)。

2
Gregory Pakosz
  1. キーワードclassで定義されたクラスのメンバーは、デフォルトでprivateです。キーワードstruct(またはunion)で定義されたクラスのメンバーは、デフォルトでpublicです。

  2. 基本クラスに対するアクセス指定子がない場合、派生クラスがpublicとして宣言されている場合はstruct、クラスがprivateとして宣言されている場合はclassが仮定されます。

  3. enum classは宣言できますが、enum structは宣言できません。

  4. template<class T>は使えますが、template<struct T>は使えません。

また、C++標準では、型をstructとして前方宣言し、その型を宣言するときにclassを使用すること、およびその逆も可能です。また、std::is_class<Y>::valueは、Yがtrueおよびstructの場合はclassですが、enum classの場合はfalseです。

2
Bathsheba

これは良い説明です: http://carcino.gen.nz/tech/cpp/struct_vs_class.php

そのため、もう一度言います。C++では、構造体のメンバーはデフォルトでパブリックの可視性を持ちますが、クラスのメンバーはデフォルトでプライベートの可視性を持ちます。

2
nutario
  • 。クラスでは、デフォルトですべてのメンバーがプライベートですが、構造ではデフォルトでメンバーはパブリックです。

    1. Structのためのコンストラクタやデストラクタのような用語はありませんが、クラスコンパイラのためにあなたが提供しなければデフォルトを作成します。

    2. Sizeof empty構造体は1バイトで、Sizeof empty構造体は0バイトです。構造体のデフォルトのアクセスタイプはpublicです。通常、データをグループ化するために構造体が使用されます。

    クラスのデフォルトアクセスタイプはprivateで、継承のデフォルトモードはprivateです。クラスは、データとそのデータを操作するメソッドをグループ化するために使用する必要があります。

    つまり、目的はデータをグループ化することであり、データの抽象化とおそらく継承が必要な場合はクラスを使用することです。

    C++では、明示的に参照解除されていない限り、構造体とクラスは値渡しされます。他の言語では、クラスと構造は異なる意味を持ちます。オブジェクト(クラスのインスタンス)は参照渡しで、構造体は値渡しです。注:この質問に関連するコメントがあります。会話に追加するには、ディスカッションページを参照してください。

1
yshivakathik

classstructの違いは、データ型間の違いではなく、キーワード間の違いです。この2つ

struct foo : foo_base { int x;};
class bar : bar_base { int x; };

どちらもクラスタイプを定義します。このコンテキストでのキーワードの違いは、デフォルトアクセスが異なることです。

  • foo::xはパブリックであり、foo_baseはパブリックに継承されます
  • bar::xはプライベートであり、bar_baseはプライベートに継承されます

他の答えには含まれていますが、明示的に言及されていません - 使用法によっては構造体はC互換です。クラスは違います。

つまり、C互換にしたいヘッダを書いているのなら、struct以外の選択肢はありません(Cの世界では関数を持てませんが、関数ポインタを持てます)。

1
UKMonkey

他の回答では、プライベート/パブリックのデフォルトについて言及しています(ただし、構造体はクラスであり、構造体であることに注意してください。2つの異なる項目ではなく、同じ項目を定義する2つの方法だけです)。

注目に値することは(特に彼が "管理されていない" C++について言及しているので質問者はMSVC++を使用しているため)、クラスがclassname__で宣言され、structname__で定義されている場合標準はそれが完全に合法であると言いますが)。

1
ymett