C++ オブジェクト指向プログラミング
参考书目:《C++面向对象程序设计》—— 谭浩强 《C++程序设计:思想与方法》—— 翁惠玉
第 2 章: クラスとオブジェクトの特性
1. オブジェクト指向プログラミング手法の概要
1. オブジェクト指向プログラミングの定義
オブジェクト指向プログラミングの考え方は、人々が日常生活で問題に対処する方法と似ています。つまり、複雑なものは必ず多くの部分から構成されます。クルマを作るとき、まずエンジンを設計・製造し、次にシャシーを設計・製造し、その後ボディやホイールを設計・製造するのではなく、エンジン、シャシー、ボディ、ホイールを別々に設計・製造し、最後にそれらを組み立てます。オブジェクトの基本的な考え方。
オブジェクト指向プログラミング要素:
- オブジェクト: 客観的な世界にあるあらゆるものはオブジェクトと見なされます。オブジェクトとしては、自然物や社会の組織構造(クラス、学校)、さらにはグラフィックや計画書等もオブジェクトとして捉えることができる。複雑なオブジェクトは、システムを構成する基本単位である単純なオブジェクトで構成されます。すべてのオブジェクトには静的特性と動的特性があります。静的な特徴(データ)は属性と呼ばれ、動的な特徴(機能)はアクションと呼ばれ、外部からオブジェクトに送信される情報は一般にメッセージと呼ばれます。通常、イベントは複数のメッセージで構成されます。
- カプセル化と情報隠蔽: オブジェクトをカプセル化し、その属性と機能の一部を外界から遮断し、これらの属性と機能を外部から見ることができなくなります。1) 関連するデータやオペレーションコードをオブジェクトにカプセル化し、プログラムの基本単位を形成し、各オブジェクトは互いに独立しており、互いに干渉しません。2) オブジェクトの特定の部分を外界から隠し、外部メッセージを受信するために外界と通信するためのインターフェイスのみを残します。この外界から隠す方法は、情報シールドと呼ばれます。C++ オブジェクトのパブリック関数は、オブジェクトの外部インターフェイスです。外部の世界は、パブリック関数を呼び出してオブジェクト内のデータ メンバーにアクセスし、指定された操作を完了します。
- 抽象化: 抽象化は、同じ種類の物事の本質を表現する方法です。物事の本質的な特性に焦点を当てます。オブジェクトは具体的であり、類似したオブジェクトのグループの共通の特徴を抽象化してクラスを形成できます (クラスは客観的世界における同様のオブジェクトのグループ) . 同じプロパティと動作を持つオブジェクトのコレクションである抽象化と記述)。つまり、クラスはオブジェクトの抽象化であり、オブジェクトはクラスの具体的なインスタンスです。
- 継承と再利用: A という名前のクラスをすでに作成している場合は、B という名前のクラスを作成する必要があります。クラス B の内容は、いくつかの属性と動作がクラス A に追加されていることを除いて、基本的にクラス A の内容と同じです。このように、クラス A に基づいて新しいコンテンツを追加するだけで済みます。これがオブジェクト指向プログラミングにおける継承メカニズムです。ソフトウェアの再利用では、過去に作成したクラスを利用できるだけでなく、他の人がクラスライブラリに配置したクラスを利用してクラスを作成することもできるため、ソフトウェアの開発サイクルが大幅に短縮されます。
- ポリモーフィズム: 似ていても同一ではない複数のオブジェクトが外界から同じメッセージを受け取ると、それぞれが異なる動作を実行する現象をポリモーフィズムと呼びます。C++ におけるいわゆるポリモーフィズムとは、継承によって生成され、そのオブジェクトが同じメッセージに対して異なる応答をする新しいクラスを指します。例えばWindowsでは、ファイルオブジェクトをマウスでダブルクリックすると、実行ファイルの場合はファイル内のプログラムが実行され、テキストファイルの場合はエディタが起動してファイルが開きます。 . これはオブジェクト指向プログラムであり、設計におけるポリモーフィズムの実践例です。
2. オブジェクト指向プログラミングの特徴
オブジェクト指向とプロセス指向の違い:
1) プロセス指向プログラミング
- プログラム = データ構造 + アルゴリズム
- 本質的に密接に関連し、客観的な事柄において相互依存しているデータとデータ処理プロセスを分離します。プロセス指向プログラミングは、データ構造に基づいたアルゴリズム設計です。
- この大幅な依存性と形式的な分離により、大規模なプログラムの作成が困難になるだけでなく、デバッグ、変更、保守も困難になります。データ構造が変更されると、関連する処理のすべてまたは一部を変更する必要が生じ、コードの再利用性が低下します。 。
2) オブジェクト指向プログラミング
- オブジェクト = データ構造 + アルゴリズム
プログラム = (オブジェクト + オブジェクト +... + オブジェクト) + メッセージ - オブジェクトに基づき、イベントまたはメッセージを使用してオブジェクトを駆動し、対応する処理を実行するプログラミング方法。
- データとデータに対する操作を相互依存した分離不可能な全体、つまりオブジェクトとしてカプセル化します。
- データ抽象化と情報隠蔽テクノロジーを使用して、この全体が新しいデータ型、つまりクラスに抽象化されます。クラスの統合レベルが高いほど、大規模なプログラムの開発に適しています。
- オブジェクト指向では、データは機能よりも安定しているため、機能中心ではなくデータ中心の方法でシステムを記述します。
プロセス指向プログラミング アプローチ VS オブジェクト指向プログラミング アプローチ
オブジェクト指向プログラミングには 2 つの側面が含まれます。
① 必要なさまざまなクラスを設計する。つまり、どのデータと操作を一緒にカプセル化するかを決定する。
②必要な操作を実現するために、オブジェクトにメッセージを送信する(オブジェクトのメンバ関数を呼び出す)方法を検討します。このとき、設計プログラムはマスター スケジューラのようなもので、各オブジェクトにメッセージ (コマンド) を送信して、これらのオブジェクトをアクティブにし (これらのオブジェクトをアクティブにし)、それぞれの責任範囲を完了します。
注:类是C++中十分重要的概念,它是实现面向对象程序设计的基础。类是所有面向对象的语言的共同特征,所有面向对象的语言都提供了这种类型。一个有一定规模的C++程序是由许多类构成的。C++支持面向过程的程序设计,也支持基于对象和面向对象的程序设计。基于对象就是基于类,基于对象的程序是以类和对象为基础的,程序的操作是围绕对象进行的。在此基础上利用继承机制和多态性,就成为面向对象的程序设计。把一组数据和相关的操作放在一起,这就是面向对象程序设计中的对象。
3. オブジェクト指向ソフトウェア開発
- オブジェクト指向分析
オブジェクト指向分析は、オブジェクト指向の概念や手法に従うものであり、課題の分析においては、客観的な物事や物事間の関係性から、関連するオブジェクト(オブジェクトの性質や振る舞い)やオブジェクト間のつながりをまとめる必要があります。 。そして、同じプロパティと動作を持つオブジェクトはクラスによって表されます。 - オブジェクト指向設計では、
オブジェクト指向の分析段階で作成した需要モデルに基づいて、各部分の具体的な設計を行いますが、最初のステップはクラス設計であり、クラスの設計には複数のレベル(継承および派生機構を使用)が含まれる場合があります。次に、これらのクラスに基づいて、アルゴリズムの設計を含むプログラミングのアイデアと方法が提案されます。設計のこの段階では、特定のコンピューター言語は関係しません。 - オブジェクト指向プログラミングは、
コンピューター言語を使用して、オブジェクト指向設計の結果に基づいてプログラムを作成します。 - オブジェクト指向テスト
オブジェクト指向テストでは、クラスをテストの基本単位として使用し、オブジェクト指向メソッドを使用したテストを実装します。 - オブジェクト指向のメンテナンス
ソフトウェア製品の使用中に、ユーザーはソフトウェアのパフォーマンスを向上させる必要がある場合があり、そのためにはプログラムの変更が必要になります。オブジェクト指向のアプローチにより、メンテナンス手順が容易になります。クラスがカプセル化されているため、1 つのクラスを変更しても他のクラス (サブクラス以外) にはほとんど影響を与えず、プログラムの保守効率が大幅に向上します。
2. クラス宣言とオブジェクト定義
オブジェクト指向プログラミングでは、多数のオブジェクトが使用されるため、プログラマは問題を分析し、クラスの概念を抽象化する必要があります。プログラムを設計する際には、最初にクラス型を宣言し、次にクラス型変数を宣言する必要があります。つまり、オブジェクトです。
1. クラスとオブジェクトの関係
クラスは、オブジェクトの特定のグループの共通点と特性を表します。オブジェクトはクラス型の変数です。クラスは抽象クラスであり、メモリ領域を占有しません。オブジェクトは固有のものであり、メモリ領域を占有します。
2. クラスタイプの宣言
クラスはユーザーが定義する必要がある型であり、プログラム内でクラス型を使用する場合は、プログラマが必要に応じて宣言するか、他の人が設計したクラスを使用することができます。クラス型の宣言は、構造体の型の宣言と似ています。
结构体声明:
struct student
{
int num;
char name[20];
char sex;
};
student st1,st2;
类声明:
class student
{
int num;
string name;
char sex;
void setdata()
{
cin >> num;
cin >> name;
cin >> sex;
}
void display()
{
cout<< num<<endl;
cout<< name<<endl;
cout<< sex <<endl;
}
};
student st1,st2;
C++ クラス定義の形式。
クラスのアクセス属性は、パブリック、プライベート、および保護です。
アクセス制御 | 属性 |
---|---|
public (パブリックメンバー) | クラスの外部インターフェイスには、このクラスのメンバー関数およびクラスのスコープ内の他の関数からアクセスできます。 |
プライベート(プライベートメンバー) | このクラスのメンバー関数のみにアクセスが許可され、クラス外からのアクセスは許可されません (フレンドを除く)。 |
保護された (保護されたメンバー) | このクラスと派生クラスのメンバー関数のみがアクセスを許可されます。 |
注:在定义类时,这三类成员不分前后顺序,也可以重复出现。一般推荐最多出现一次。
3. オブジェクトのメソッドを定義する
- 最初にクラス型を宣言してから、オブジェクトを定義します。
クラス クラス名 オブジェクト名 テーブル
クラス 学生 st1、st2;
クラス名 オブジェクト名 テーブル
学生 st1、st2; - オブジェクトはクラス型の宣言と同時に定義されます。
class クラス名
{ private: … public: … } オブジェクト名のリスト; - クラス名は表示されず、オブジェクトは直接定義されます (このメソッドは C++ では有効ですが、使用はお勧めできません)。
class
{ private: ... public: ... } オブジェクト名テーブル;
4. クラス型と構造体型の違い
class で宣言されたクラスにメンバー アクセス修飾子がない場合、すべてのメンバーはデフォルトで private に制限され、
struct で宣言されたクラスにメンバー アクセス修飾子がない場合、すべてのメンバーはデフォルトで public に制限されます。
3. クラスのメンバ関数
クラスを宣言するときは、クラスのメンバー関数と呼ばれる、クラスのデータ メンバーにアクセスする関数を定義する必要があります。
- メンバー関数のプロパティ クラス
メンバー関数は、このクラスのすべてのメンバーにアクセスできる関数の一種です。一般的な方法は、クラスと外部の世界の間のインターフェイスとして、外部と通信する必要があるメンバー関数をパブリックとして指定することです。 - クラス外にメンバ関数を定義する形式
: type クラス名::関数名(仮引数リスト)
{メンバ宣言}
class student
{
int num;
string name;
char sex;
public:
void setdata();
void display();
};
void student :: setdata()
{
cin >> num;
cin >> name;
cin >> sex;
}
void student :: display()
{
cout<< num<<endl;
cout<< name<<endl;
cout<< sex <<endl;
}
student st1,st2;
注:(1)在类外定义成员函数时,必须在函数中增加类名,用于限定它属于哪个类,::是作用域限定符或称作用域运算符。上面的例子中如果函数不用成员访问限定符,函数就成了全局作用域中的display函数而不是成员函数。(2)如果在::前不带类名,或函数名前既无类名又无作用域运算符::,表示该函数是全局函数。(3)类的实现内容通常较大,为了便于阅读、管理和维护,最好将一个类拆分成一个.cpp文件和一个.h文件。
- 組み込み関数
C++ のデフォルトでは、クラス内でインライン関数として定義されたメンバー関数が使用されます。メンバー関数がクラスの外部で定義されている場合、システムはデフォルトでそれをインライン メンバー関数として扱いません。この場合、inline キーワードは次のように指定する必要があります。関数を宣言するときに関数の前に追加します。
class student
{
int num;
string name;
char sex;
public:
inline void setdata()
inline void display()
};
- メンバ関数の格納方法。
オブジェクトがクラスで定義されている場合、システムはオブジェクトごとにメモリ領域を割り当てます。同じクラスのオブジェクトのメンバ関数は同じです。各オブジェクトのメンバ関数がメモリ領域を割り当てると、大量のメモリ領域が発生します。無駄の。C++ がこれを処理する方法は、オブジェクトのデータ メンバーにのみメモリ空間を割り当て、クラスのすべてのオブジェクトがメンバー関数空間を共有することです。
4. オブジェクトメンバーへの参照
オブジェクトを定義すると、オブジェクト内のパブリック メンバー (データ メンバーまたはメンバー関数) にプログラムから直接アクセスできます。プログラム内のオブジェクト メンバーにアクセスするには、次の 3 つの方法があります。
- オブジェクト名とメンバー演算子を使用してメンバーにアクセスします
形式: オブジェクト名.メンバー名
例: st1.display(); // メンバー関数を呼び出します
display(); // 通常の関数を呼び出します。
注:只有成员函数可以访问类中的所有成员,而在类外只能访问公有成员。
- オブジェクトへのポインタを使用したメンバーへのアクセス
class Time
{
public:
int hour;
int minute;
};
Time t, *p;
p= &t;
cout<< p->hour<<endl;
注·:p->hour表示p当前指向对象t中的成员hour, 此时(*p).hour也代表对象t中的成员hour,在这个例子中,p->hour、(*p).hour、t.hour三种表示是一个意思。
- オブジェクト参照を使用してメンバーにアクセスします。
オブジェクト A の参照 B を定義すると、B はオブジェクト A の別名になります。A と B は両方ともオブジェクトなので、参照によってオブジェクトのメンバーにアクセスできます。
例: Time t1;
Time & t2=t1;
cout<< t2.hour;
ここで、t2 は t1 のエイリアスであるため、t2.hour にアクセスすることは t1.hour にアクセスすることになります。
注:类的成员可以是其他类的对象,但不能以类自身的对象作为本类的成员,而类自身的指针和引用可以作为类的成员。
5. クラスとオブジェクトの簡単な適用
例1:出力時刻(時:分:秒)
#include <iostream>
using namespace std;
class Time
{
public:
int hour;
int minute;
int sec;
};
//第一种
int main()
{
Time t1;
cin>>t1.hour >>t1.minute>>t1.sec;
cout<<t1.hour<<":"<<t1.minute<<":"<<t1.sec<<endl;
Time t2;
cin>>t2.hour>>t2.minute>>t2.sec;
cout<<t2.hour<<":"<<t2.minute<<":"<<t2.sec<<endl;
return 0;
}
//第二种
int main()
{
void set_time( Time& ) ; // 使用引用形参
void show_time( Time& );
Time t1;
set_time(t1);
show_time(t1);
Time t2;
set_time(t2);
show_time(t2);
return 0;
}
void set_time(Time& t)
{
cin>>t.hour;
cin>>t.minute;
cin>>t.sec;
}
void show_time(Time& t)
{
cout<<t.hour<<":"<<t.minute<<":"<<t.sec<<endl;
}
//第三种
#include <iostream>
using namespace std;
class Time
{
public:
void set_time() ;
void show_time();
private:
int hour;
int minute;
int sec;
};
int main()
{
Time t1;
t1.set_time();
t1.show_time();
Time t2;
t2.set_time();
t2.show_time();
return 0;
}
void Time::set_time()
{
cin>>hour;
cin>>minute;
cin>>sec;
}
void Time::show_time()
{
cout<<hour<<":"<<minute<<":"<<sec<<endl;
}
例 2: 整数配列の最大値を見つける
#include <iostream>
using namespace std;
class Array_max
{
public:
void set_value();
void max_value();
void show_value();
private:
int array[10];
int max;
};
void Array_max::set_value()
{
int i;
for (i=0;i<10;i++)
cin>>array[i];
}
void Array_max::max_value()
{
int i;
max=array[0];
for (i=1;i<10;i++)
if(array[i]>max) max=array[i];
}
void Array_max::show_value()
{
cout<<"max="<<max;
}
int main()
{
Array_max arrmax;
arrmax.set_value();
arrmax.max_value();
arrmax.show_value();
return 0;
}
6.学級閉鎖と情報隠蔽
1. パブリックインターフェースとプライベートインターフェースの分離を実現
C++ はクラスを通じてカプセル化を実現します。クラスの機能は、データとデータをクラス型で操作するためのアルゴリズムをカプセル化することです。クラスを宣言するとき、通常、データ メンバーは外部から隔離するためにプライベートとして指定され、外部から呼び出されるメンバー関数はパブリックとして指定されます。外部からはパブリック関数を通じてデータ メンバーにアクセスできます。外界とオブジェクト間の唯一の接続は、パブリック メンバー関数を呼び出すことです。パブリック メンバー関数は、ユーザーが使用するクラスのパブリック インターフェイスです。ユーザーは、パブリック メンバー関数を呼び出して、特定の関数を実装できます。ユーザーは、各パブリック メンバー関数の機能を理解するだけでよく、これらの関数がどのように実装されるかを理解する必要はありません。これが、インターフェイスと実装の分離です。
ユーザーがパブリック メンバー関数を恣意的に変更してデータの操作を変更することを防ぐために、ユーザーはパブリック メンバー関数のソース コードを表示できないことがよくあります。クラス内のデータはプライベートであり、データ操作の実装の詳細はユーザーには隠されており、この実装はプライベート実装と呼ばれます。このクラスのパブリック インターフェイスとプライベート実装を分離すると、情報が隠蔽されます。
情報隠蔽の利点は次のとおりです。
(1) クラスの関数を変更または拡張する場合、クラス内の関連するデータ メンバーとメンバー関数のみを変更するだけで済み、クラス外の部分を変更する必要はありません。変更されました。インターフェイスが実装 (データの操作) から分離されている場合、クラスのインターフェイスが変更されない限り、プライベート実装への変更はプログラムの他の部分に影響を与えません。
(2) コンパイル中にクラス内のデータの読み取りおよび書き込みのエラーが見つかった場合、プログラム全体をチェックする必要はなく、そのデータにアクセスするこのクラスのメンバー関数だけをチェックする必要があります。これにより、プログラム (特に大規模なプログラム) の設計、変更、デバッグが便利かつ簡単になります。
2. クラス宣言とメンバ関数定義の分離
オブジェクト指向プログラムを開発する場合、通常、クラスの宣言(メンバ関数の宣言を含む)は指定されたヘッダファイル内に配置され、該当するヘッダファイルをプログラムにインクルードするだけで済みます。プログラム内でクラス宣言を繰り返す必要はありません。もう 1 つの方法は、クラスのメンバー関数をヘッダー ファイルに定義せずに、別のファイルに配置することです。
実際には、同様の機能を持つ一般的に使用されるクラス宣言がいくつか集められて、クラス ライブラリが形成されます。クラス ライブラリには、C++ コンパイル システムによって提供される標準クラス ライブラリとユーザー クラス ライブラリが含まれます。
クラス ライブラリには 2 つのコンポーネントがあります:
(1) クラス宣言ヘッダー ファイル
(2) コンパイルされたメンバー関数定義 (オブジェクト ファイル)。
ユーザーは、クラス ライブラリを C++ コンパイル システムのサブディレクトリにロードし、include コマンドを使用してクラス宣言のヘッダー ファイルをプログラムにインクルードする限り、これらのクラスとそのメンバー関数を使用できます。