C++のstructとclassの違いとC++this変数とconst変数のタイプ


C++言語ではclassがクラスを定義するキーワードであり、C++ではstructを使用してクラスを定義することもできます.両者の違いは、classで定義されたクラスで、データ・メンバーまたはメンバー関数が説明されていない場合はprivate(プライベート)がデフォルトで、structで定義されている場合はpublic(共通)がデフォルトです.  
#include<iostream>   
using namespace std;   

class C {  
          public:   
                 int getAge() const {   return age;   }   
                 void setAge( int n ) {   age = n;   }   
           private:   int age;   
        };   
int main() {  
                 C c;   c.setAge( 22 );  
                 cout << "My age: " << c.getAge() << endl;  
                 return 0;
  }

オブジェクト向けプログラム設計の基礎としてclassの基本構造と特性を把握することが重要である.
1.classを実装する方法
class egclass {

public:

       //public                

       //                member functions

//     constructor(    ) destructor(    )

private:

              //       

              //member functions     

              //  data members

              //       data members      data member     constructor 

}

すべてのmemberfunctionsはclassで宣言しなければならない.定義を同時に与えるかどうかは、自分で決めることができる.classボディ内で定義されている場合、このmemberfunctionsはinline関数とみなされます(注:inline関数はマクロに相当します).classの体外でmemberfunctionsを定義する場合は、どのclassに属するかを特定の構文で指定する必要があります.この関数をinline関数にする場合は、一番前にキーワードinlineを指定します.
Inlne bool stack::empty()
{
       //  member functions
}

上記の例では、empty()がclass stackのmemberfunctionsであることを示しています.Class名の後の2つのコロン(stack:::)はclass scoperesolution(クラス範囲決定)演算子と呼ばれます.このmember functionsを示すために使用される
どのclassに属していますか.
2.Constructors(コンストラクション関数)とdestructors(コンストラクション関数)
Constructorsはdata membersを初期化するために使用されます.コンパイラはclass objectが定義されるたびにconstructorsを呼び出してdata membersを初期化します.
Constructorsの関数名はclass名と同じである必要があります.またconstructorsは戻り値を指定するべきではなく、値を返す必要はありません.オーバーロードできます.最もclassのmemberfunctionsはclassの体外で定義することができる.
egclass::egclass();//これは最も簡単なconstructorです
Destructorの場合、constructorsに対向するmember functions.その定義はユーザが自分で決定する.
classにdestructorsがある場合.objectがライフを終了すると、コンパイラはdestructorsを自動的に呼び出します.desrructorは主にconstructorsまたはオブジェクト実行サイクルで構成されたリソースを解放するために使用されます.
Destructorsの命名は非常に厳格で、その関数名はclass名に「~」を付けなければならない.パラメータも値も返されません.さらにoverloadedは不可能です.eg:
~egclass()

{

       //      

}

       Member Initialization List (     )

         constructors   data member     ,         

       egclass::egclass (const egclass &rhs)

       {

              _data_member1=rhs._data_member1;

       _data_member2=rhs._data_member2;

}
であり、別の初期化構文は、いわゆるMember Initialization List(メンバー初期値テーブル)である.
egclass::egclass (const egclass &rhs): _data_member1(rhs._data_member1),

                                                    _data_member2(rhs._data_member2)

{    }           //         

3.const(不変)とmutable(可変)
関数がclassを呼び出すと、このclassが変更されないことを保証できます.
int sum( const egclass &class1)

{

       //      

}
しかしsumがこのclassの1つのmember functionsを呼び出した場合、このclassの値はその1つのmemberfunctionsによって変更される可能性がある.このclassの値がそのmember functionsによって変更されないようにします.コンパイラにclass objectが変更されないことを伝えるには、memberfunctionsにconstをマークする必要があります.
Class egclass {

Public:

       //   const member functions       class object

       int length() const;

       int ended() const;

       //    non-const member functions

       int nex();

private:

       //…

}

constはmember functionsのパラメータテーブルに接続する必要があります.classの体外定義のconst memberfunctionsの場合は、宣言と定義の両方でconstを指定する必要があります.
キーワードmutableは、data memberに、その値が変更されるとclass objectの定数性を破壊しないという性質を持たせることができる.
4.thisポインタ
この例を見てみましょう.
Stack & Stack::

transfer(const stack &rhs)

{

       _ip=rhs_ip;

       _size=rhs._size;

       return ???                 //             ?

}

このポインタはこの問題を解決するものです.Thisポインタはmember functionsで呼び出し者をアドレスするために使用され、このとき戻り値はreturn*thisと書くことができる.
メンバーfunctions全体をこのように書き換えることができます
Stack & Stack::

transfer(const stack &rhs)

{

       if (this !=&rhs){

       _ip=rhs_ip;

       _size=rhs._size;

       }

       return *.this;    

}

C++におけるstructとclassの違い
C++のstructはCのstructを拡張し、異なるデータ型を含むデータ構造だけでなく、多くの機能を取得しています.
structにはメンバー関数が含まれますか?できる!
structは継承できますか?できる!
structはマルチステートを実現できますか?できる!!!
最も本質的な違いは、デフォルトのアクセス制御であり、2つの側面に現れています.
1)デフォルトの継承アクセス権.structはpublicで、classはprivateです.
次のコードを書きます.
struct A

    {

          char a;

    };

    struct B : A

    {

          char b;

    };
このときBはpublicがAを継承している.上記のstructをclassに変更すると、BはprivateがAを継承します.これがデフォルトの継承アクセス権です.だから私たちは普段クラス継承を書くとき、通常このように書きます.
    struct B : public A
デフォルトのprivateではなくpublic継承であることを示すためです.
もちろん、デフォルトがpublic継承なのかprivate継承なのかは、ベースクラスではなくサブクラスに依存します.structはclassを継承することができ、同じclassもstructを継承することができます.デフォルトの継承アクセス権は、サブクラスがstructを使用しているのかclassを使用しているのかを見ることです.次のようになります.
    struct A{   };
    class B : A{   };//private継承
    struct C : B{   };//public継承
2)structはデータ構造の実装体として、デフォルトのデータアクセス制御はpublicであり、classはオブジェクトの実装体として、デフォルトのメンバー変数アクセス制御はprivateである.
3)「class」というキーワードは、「typename」のようにテンプレートパラメータを定義するためにも使用されます.ただし、キーワード「struct」はテンプレートパラメータを定義するために使用されません.
4)やはり上述したように,C++のstructはCのstructの拡張であり,拡張である以上,過去のCのstructが持つべきすべての特性と互換性を持たなければならない.たとえば、次のように書くことができます.
  struct A    //    struct

    {

         char c1;

         int  n2;

         double db3;

    };

    A a={'p',7,3.1415926};  //       
すなわちstructは、定義時に{}で初期値を付与することができる.
上のstructに構造関数(または虚関数)を追加すると、structも{}で初期値を付与できません.
確かに、{}のように初期値を付与するのは、1つの初期化リストでデータを順番に初期化するだけで、A a={'p',7}と書くと、c 1,n 2は初期化され、db 3は初期化されない.このような簡単なcopy操作は、オブジェクトに置くべきではなく、簡単なデータ構造でのみ発生します.コンストラクション関数または虚関数を追加するとstructはオブジェクトの特性をより反映し、この{}操作を有効にしません.実際,このような関数を加えることでクラスの内部構造が変化する.普通のメンバー関数を追加しますか?{}は依然として利用可能であることがわかります.実際には、一般的な関数をデータ構造のアルゴリズムとして理解することができます.これは、データ構造の特性を破るものではありません.虚関数と普通のメンバー関数の違いについては、具体的に文章を書いて議論します.
そこで,ここではstructが{}で初期値を付与しようとしても,クラスの特性ではなくデータ機構をより体現するために多くの制約条件を満たさなければならないことを見出した.ではなぜstructをclassに変えるだけでは使えないのでしょうか.実は問題はちょうど私たちが前に話した訪問制御です.何を忘れたの?はい、structをclassに変更すると、アクセス制御がpublicからprivateに変わります.もちろん{}で初期値を割り当てることはできません.publicを加えると、classも{}使えるし、structと変わらない!!!上記の違いから、
structはデータ構造の実装体と見なすのに適しており、classはオブジェクトの実装体と見なすのに適している.
二、
カッコでclassとstructを初期化する構造関数を定義した場合、カッコで初期化することはできません.構造関数を定義していない場合、structはカッコで初期化できます.コンストラクション関数が定義されず、すべてのメンバー変数がpublicである場合は、カッコで初期化できます.デフォルトアクセスclassのデフォルトのメンバーアクセスはprivateであり、structはpublicです.継承方式class継承のデフォルトはprivate継承であり、struct継承のデフォルトはpublic継承である.次のコードを見てみましょう(コンパイラから与えられたエラー情報を見てください):
class T1
{
 public:
  void f()
  {
   cout<<"T1::f()"<<endl;
  }
 int x,y;
};
struct T2
{
 int x;
 void f(){cout<<"T2::f()"<<endl;}
};
struct TT1 : T1
{
};
class TT2 : T2
{
};
int main()
{
 TT1 t1;
 TT2 t2;
 t1.f();
 t2.f();
}

テンプレートについて
テンプレートでは、タイプパラメータの前にclassまたはtypenameを使用できます.structを使用すると、意味が異なります.structの後ろには「non-type template parameter」が付いていますが、classまたはtypenameの後ろにはタイプパラメータが付いています.
template <struct X>
void f(X x)
{
}
//    :d:codecpptestcpptestcpptest.cpp(33) : error C2065: 'X' : undeclared identifier