C++ノート1(オブジェクト向けプログラミング上)

11033 ワード

C++プログラミングの概要:
1.1 C++履歴
(1)C++は1983年に登場し,当時はC with Classと呼ばれていた.(2)歴史バージョン:C++98(1.0)、C++03(TR 1,Technical Report 1)、C++11(2.0)、C++14、C++17(2017年に出たばかり).(3)C++はC++言語とC++標準ライブラリからなる.
1.2 C++のclass経典分類
(1)C++without pointer members(カリキュラム例Complex).(2)C++with pointer members(カリキュラム例String).
1.3 Object BasedとObject Oriented
(1)Object Based(オブジェクトベース)は単一classの設計に直面する.(2)Object Oriented(オブジェクト指向,オブジェクト指向)は多重classの設計,classesとclassesの関係に直面する.
二頭ファイルとクラスの宣言
2.1 C++とCの違い
CとC++データと関数の違いについて:(1)Cにはデータと関数があり、データ型に応じて具体的なデータを作成し、関数はこれらのデータを処理し、弊害はこれらのデータがグローバルであり、その後エラーが発生する可能性がある.(2)C++はデータとこれらのデータを処理する関数をカプセル化したもので,classまたはstructと呼ばれ,C++ではclassとstructはわずかな違いしかない.
2.2 class古典分類のデータ領域と関数
(1)C++ポインタを持たないクラスcomplexデータ領域は複数の実部および虚部であり、メンバー関数は加算、減算、乗算、除算、共役、正弦などである.(2)C++ポインタ付きクラスstringデータ領域は文字であり,実際にはポインタであり,文字列を指し,メンバー関数はコピー,出力,付加,挿入などである.
2.3 C++基本コード形式
(1)C++の基本コード形式:クラス宣言(.h)+main関数+クラス定義(.cpp)+標準ライブラリ(.h)(2)C++拡張ファイル名は必ずしも.hまたは.cpp、かもしれません.hppまたは他の延長名さえありません.(3)CとC++の出力に関するヘッダファイルの違いは、Cのヘッダファイルがstdioである.h,C++のヘッダファイルはiostreamです.
2.4ヘッダファイル防衛式声明
#ifndef  _COMPLEX_
#define  _COMPLEX_
、、、
#endif

ヘッダー・ファイルには、同じヘッダー・ファイルが複数回含まれるため、定義が重複することを防止するための防衛声明を書く必要があります.
2.5ヘッダファイルレイアウト
#ifndef  _COMPLEX_
#define  _COMPLEX_

#include

class ostream;        //    
class complex;
complex&
 _doapl(complex* ths,const complex &r);

class complex         //   
{
...
};

complex::function...  //   
#endif

(1)ヘッダファイルレイアウトは、防衛宣言、ヘッダファイルを含むほか、前置宣言、クラスの宣言、クラスの定義の3つの主要部分を含む.(2)クラスの宣言にはクラスのヘッダ(head)とクラスのボディ(body)が含まれ,ある関数はクラスのbodyに定義され,ある関数はクラスのbodyの外に定義される.
2.6クラステンプレートの初回体験
template
class complex
{
public:
      complex(T r = 0,T i = 0)
      : re ( r ) , im ( i )
      {}
      complex& operator +=(const complex&);
      T real() const { return re;}
      T imag() const { return im;}
private:
      T re,im;
      friend complex& _doapl (complex*,const complex&);
};
void main()
{
      complex c1(2.5,1.5);
      complex c2(2,6);
      ...
}

クラスのメンバー変数のタイプを制限しないように、テンプレート形式でメンバー変数を定義し、後で必要なときにデータ型を定義します.
さんこうぞうかんすう
3.1 inline(インライン)関数
class complex
{
public:
       complex(double r = 0,double i = 0)
       :re (r) ,im ( i )
       { }
       complex& operator +=(const complex&);
       double real() const { return re;}      //    inline   
       double imag() const { return im;}
private:
       double re,im;
       friend complex& _doapl (complex*,const complex&);
};
inline double
imag(const complex& x)
{
       return x.imag();
}

関数がclass本体内で定義されている場合、自動的にインライン関数候補になり、インライン関数の効率が高くなります.関数が複雑(たとえば、関数内にループ、再帰など)またはコードが長い場合、コンパイラはそれをインライン関数に変えることはできません.
3.2クラスのアクセスレベル
クラスのボリュームにはpublic、protect、privateの3つのアクセスレベルがあります.(1)private:クラス内の関数、その友元関数のみがアクセスでき、他のアクセスはできず、クラスのオブジェクトもアクセスできません.(2)protected:クラス内の関数、サブクラスの関数、およびそのメタ関数によってアクセスできますが、クラスのオブジェクトにはアクセスできません.(3)public:このクラスの関数,サブクラスの関数,そのメタ関数によってアクセスされてもよいし,そのクラスのオブジェクトによってアクセスされてもよい.
3.3コンストラクタ
class complex
{
public:
       complex(double r = 0,double i = 0)  //          ,    
       :re (r) ,im ( i )                   //     
       { }
       complex& operator +=(const complex&);
...
}

コンストラクション関数:オブジェクトの作成時に自動的に呼び出される関数.(1)クラスの名前と同じで、デフォルトのパラメータがあり、タイプを返す必要はありません.(2)より良い方法は,コンストラクション関数を用いて初期化リストを行い,初期化リストはコンパイル前に実行され,コンストラクション関数の括弧内に初期値を付与するよりも効率が高く,初期値はコンパイル後に実行される.(3)コンストラクション関数は,関数のリロードと呼ばれる複数の関数を持つことができる.
四パラメータ伝達と戻り値
4.1 singleton設計モード
class A{
public:
      static A& getInstance();
      setup() {...}
private:
      A();
      A(const A& ths);
     ...
};

A& A::getInstance()
{
      static A a;
      return a;
}

コンストラクション関数がprivate領域に配置されると、このクラスは外部でオブジェクトを作成できないことを示します.設計モードSingleton:外部はgetInstance関数を呼び出すことによってしかAのオブジェクトを得ることができず、Aのオブジェクトを直接作成することはできません.
4.2 const初体験
class complex
{
...
     double real() const {return re;)
     double imag() const {return im;)
...
}
void main()
{
     const complex c1(2,1);
     cout<

const修飾関数は、外部から呼び出されたときに中のデータが変更されないことを示します.使用者がオブジェクトを作成するときにconstを追加しますが、クラス内の関数はconstを使用していません.エラーが発生します.
4.3パラメータ伝達と戻り値
(1)パラメータ伝達伝達伝達参照は伝達値より効率的であり,伝達参照は伝達ポインタと同様に速い(4バイト)が,形式はポインタよりもきれいである.伝引用はまたこの関数が伝入するものを変えたくなくて、前にconstで修飾することができます.(2)戻り値は,許容される場合にできるだけ参照を伝達する.ローカル変数を返します.参照は転送できません.
4.4友元関数
class complex
{public:
       complex(double r = 0,double i = 0)
       :re (r) ,im ( i )
       { }
       int func(const complex& param)
       {return param.re+param.im;}
private:
       double re,im;
};
void main()
{
       complex c1(2,1)
       complex c2;
       c2.func(c1);
}

(1)友元関数はfriendのprivateメンバーを自由に取得でき,友元はc++のパッケージ性を破った.(2)同じclassの各objectsは互いに友元である.
5オペレータのリロードと一時オブジェクト
5.1 thisポインタ
通常class定義でタイプ変数自体を使用する場合、変数名が分からないため(汎用的にも実際の変数名を固定することは不可能)、thisのようなポインタで変数自体を使用します.参照リンク:http://blog.csdn.net/feiyond/article/details/1652505
5.2オペレータのリロード——メンバー関数
inline complex& 
_doapl(complex* ths, const complex& r) //do assignment plus 
{
     ths->re += r.re;
     ths->im += r.im;
     return *ths;
}

inline complex& 
complex::operator += (const complex& r)
{
     return _doapl (this,r) ;
}
//           
/*inline complex&      
complex::operator += (this, const complex& r)
{
    return _doapl (this,r) ;
}*/
void main()
{
    complex c1(2,1);
    complex c2(5);

    c2 += c1 ;
}

(1)すべてのメンバー関数関数には、非表示のパラメータであるthisポインタがあります.(2)+=演算子をリロードし、voidではなくcomplex&を返します.c 2+=c 1の場合、戻り値を知る必要はありませんが、:c 3+=c 2+=c 1の場合、戻り値voidがエラーになります.
5.3オペレータの再ロード——非メンバー関数
inline complex
operator + (const complex& x,const complex& y)
{
      return complex (real (x)+real (y),imag (x)+imag (y));
}
inline complex
operator + (const complex& x,const complex& y)
{
      return complex (real (x)+ y ,imag (x));
}
inline complex
operator + (const complex& x,const complex& y)
{
      return complex ( x +real (y),imag (y));
}
void main()
{
      complex c1(2,1);
      complex c2;
      complex();
      complex(4,5);
      c2 = c1 + c2;  //      
      c2 = c1 + 5;   //     
      c2 = 7 + c1;   //     
      cout<

+リロード関数がグローバル関数であれば,実数+複素と複素+実数の場合は考えられず,複素加算実数の場合のみ考えられる.一時オブジェクトtypename():次の行が終了するまで一時オブジェクトを作成することを示します.これらの一時オブジェクトは、return by referenceではありません.なぜならlocal objectだからです.
5.4まとめ
(1)コンストラクション関数はできるだけ初期化リストを用いる.(2)関数にconstを付けるべきかどうかは必ず考慮しなければならない.(3)パラメータの伝達はできるだけ引用を用い,constを加えるかどうかは考慮する.(4)戻り値はできるだけ参照を用い、可能な場合;(5)データはできるだけprivateに、関数はできるだけpublicに置く.
6 Complexクラスの完全なコード:
#ifndef __MYCOMPLEX__
#define __MYCOMPLEX__

class complex; 
complex&
  __doapl (complex* ths, const complex& r);
complex&
  __doami (complex* ths, const complex& r);
complex&
  __doaml (complex* ths, const complex& r);


class complex
{
public:
  complex (double r = 0, double i = 0): re (r), im (i) { }
  complex& operator += (const complex&);
  complex& operator -= (const complex&);
  complex& operator *= (const complex&);
  complex& operator /= (const complex&);
  double real () const { return re; }
  double imag () const { return im; }
private:
  double re, im;

  friend complex& __doapl (complex *, const complex&);
  friend complex& __doami (complex *, const complex&);
  friend complex& __doaml (complex *, const complex&);
};


inline complex&
__doapl (complex* ths, const complex& r)
{
  ths->re += r.re;
  ths->im += r.im;
  return *ths;
}
 
inline complex&
complex::operator += (const complex& r)
{
  return __doapl (this, r);
}

inline complex&
__doami (complex* ths, const complex& r)
{
  ths->re -= r.re;
  ths->im -= r.im;
  return *ths;
}
 
inline complex&
complex::operator -= (const complex& r)
{
  return __doami (this, r);
}
 
inline complex&
__doaml (complex* ths, const complex& r)
{
  double f = ths->re * r.re - ths->im * r.im;
  ths->im = ths->re * r.im + ths->im * r.re;
  ths->re = f;
  return *ths;
}

inline complex&
complex::operator *= (const complex& r)
{
  return __doaml (this, r);
}
 
inline double
imag (const complex& x)
{
  return x.imag ();
}

inline double
real (const complex& x)
{
  return x.real ();
}

inline complex
operator + (const complex& x, const complex& y)
{
  return complex (real (x) + real (y), imag (x) + imag (y));
}

inline complex
operator + (const complex& x, double y)
{
  return complex (real (x) + y, imag (x));
}

inline complex
operator + (double x, const complex& y)
{
  return complex (x + real (y), imag (y));
}

inline complex
operator - (const complex& x, const complex& y)
{
  return complex (real (x) - real (y), imag (x) - imag (y));
}

inline complex
operator - (const complex& x, double y)
{
  return complex (real (x) - y, imag (x));
}

inline complex
operator - (double x, const complex& y)
{
  return complex (x - real (y), - imag (y));
}

inline complex
operator * (const complex& x, const complex& y)
{
  return complex (real (x) * real (y) - imag (x) * imag (y),
               real (x) * imag (y) + imag (x) * real (y));
}

inline complex
operator * (const complex& x, double y)
{
  return complex (real (x) * y, imag (x) * y);
}

inline complex
operator * (double x, const complex& y)
{
  return complex (x * real (y), x * imag (y));
}

complex
operator / (const complex& x, double y)
{
  return complex (real (x) / y, imag (x) / y);
}

inline complex
operator + (const complex& x)
{
  return x;
}

inline complex
operator - (const complex& x)
{
  return complex (-real (x), -imag (x));
}

inline bool
operator == (const complex& x, const complex& y)
{
  return real (x) == real (y) && imag (x) == imag (y);
}

inline bool
operator == (const complex& x, double y)
{
  return real (x) == y && imag (x) == 0;
}

inline bool
operator == (double x, const complex& y)
{
  return x == real (y) && imag (y) == 0;
}

inline bool
operator != (const complex& x, const complex& y)
{
  return real (x) != real (y) || imag (x) != imag (y);
}

inline bool
operator != (const complex& x, double y)
{
  return real (x) != y || imag (x) != 0;
}

inline bool
operator != (double x, const complex& y)
{
  return x != real (y) || imag (y) != 0;
}

#include 

inline complex
polar (double r, double t)
{
  return complex (r * cos (t), r * sin (t));
}

inline complex
conj (const complex& x) 
{
  return complex (real (x), -imag (x));
}

inline double
norm (const complex& x)
{
  return real (x) * real (x) + imag (x) * imag (x);
}

#endif   //__MYCOMPLEX__