Cpp クラス 抽象クラス 新しいページはコチラ
提供: yonewiki
(ページの作成:「C++に戻る <table class="mbox-small" style="border:1px solid #aaa; background-color:#f9f9f9; width:22em;" id="RealTitleBanner"> <tr>...」) |
|||
5行: | 5行: | ||
<tr> | <tr> | ||
<td style="width:1px;"></td> | <td style="width:1px;"></td> | ||
− | <td class="mbox-text plainlist" style="">本来の表記は「<b><span id="RealTitle" style="font-size:large;">C++ クラス 抽象クラス</span></b>」です。この記事に付けられた題名は{{記事名の制約}}から不正確なものとなっています。</td> | + | <td class="mbox-text plainlist" style="">本来の表記は「<b><span id="RealTitle" style="font-size:large;">C++(Cpp) クラス 抽象クラス</span></b>」です。この記事に付けられた題名は{{記事名の制約}}から不正確なものとなっています。</td> |
</tr> | </tr> | ||
</table> | </table> | ||
11行: | 11行: | ||
<br /> | <br /> | ||
== '''クラス 抽象クラス''' == | == '''クラス 抽象クラス''' == | ||
+ | 抽象クラスは、単体ではもう機能しないような基底クラスになってしまう手法で、先の記事で説明した仮想関数を使う時に基底クラスにはプログラムの実体を持たない方法です。[[Cpp クラス 仮想関数]]で使っていたプログラムでは基底クラスは2箇所をvirtualキーワードで仮想関数にしていましたが、そのうちのmfVirtual_vDispValue()に変更して、基底クラスだったCBaseInheritanceを抽象クラスにしたいと思います。 | ||
+ | |||
+ | まずは元々の基底クラスはこうだったという例を示します。 | ||
+ | |||
+ | |||
+ | <span style="color: #ffffff; background-color: #555555; padding: 0px 5px 0px 5px; display: inline-block;">cpp <span>(</span>基底クラス BaseInheritance.h<span>)</span><!-- padding 上 右 下 左--> | ||
+ | <syntaxhighlight2 lang="cpp" line start=1> | ||
+ | #ifndef __BASEINHERITANCE_H_YONET__ | ||
+ | #define __BASEINHERITANCE_H_YONET__ | ||
+ | #if _MSC_VER > 1000 | ||
+ | #pragma once | ||
+ | #endif | ||
+ | |||
+ | class CBaseInheritance { | ||
+ | protected: | ||
+ | int m_iBaseMoney = 0; | ||
+ | int m_iBaseMonth = 0; | ||
+ | int m_iMoney = 0; | ||
+ | int mf_iBaseSumMoney(); | ||
+ | public: | ||
+ | CBaseInheritance(); | ||
+ | CBaseInheritance(int iArgBaseMoney, int iArgBaseMonth); | ||
+ | virtual ~CBaseInheritance(); | ||
+ | virtual void mfVirtual_vDispValue(); | ||
+ | void mf_vBaseDispValue(); | ||
+ | }; | ||
+ | #endif | ||
+ | </syntaxhighlight2> | ||
+ | |||
+ | 基底クラスの仮想関数がありましたが、基本料金が0円だったかどうかも、必ず知りたいとしたら、オプションが0円だったということも含めて呼びだされたいため、このクラスがそのまま使われるとまずいという考え方もできます。基底クラスが直接呼ばれたら、オプション料金の設定忘れということになってしまいます。ならば、基本料金を返却表示してしまう部分は派生クラスでプログラムされて、かつ基底クラスではプログラムを持たない形式にすると良いと考えることが出来ます。こういった、基底クラスの関数が派生クラスに全投げする状態の関数を純粋仮想関数と言います。 | ||
+ | |||
+ | |||
+ | 純粋仮想関数として定義するのも仮想関数がvirtualというキーワードを付けるだけだったの同様に簡単で、仮想関数を0で初期化することで、宣言だけで、プログラムを持つ必要がなくなります。具体的には以下のようになります。 | ||
+ | |||
+ | <span style="color: #ffffff; background-color: #555555; padding: 0px 5px 0px 5px; display: inline-block;">cpp <span>(</span>基底クラス BaseInheritance.h<span>)</span><!-- padding 上 右 下 左--> | ||
+ | <syntaxhighlight2 lang="cpp" line start=101> | ||
+ | #ifndef __BASEINHERITANCE_H_YONET__ | ||
+ | #define __BASEINHERITANCE_H_YONET__ | ||
+ | #if _MSC_VER > 1000 | ||
+ | #pragma once | ||
+ | #endif | ||
+ | |||
+ | class CBaseInheritance { | ||
+ | protected: | ||
+ | int m_iBaseMoney = 0; | ||
+ | int m_iBaseMonth = 0; | ||
+ | int m_iMoney = 0; | ||
+ | int mf_iBaseSumMoney(); | ||
+ | void mf_vBaseDispValue(); | ||
+ | public: | ||
+ | CBaseInheritance(); | ||
+ | CBaseInheritance(int iArgBaseMoney, int iArgBaseMonth); | ||
+ | virtual ~CBaseInheritance(); | ||
+ | virtual void mfVirtual_vDispValue() = 0; | ||
+ | }; | ||
+ | #endif | ||
+ | </syntaxhighlight2> | ||
+ | |||
+ | と118行目のように | ||
+ | |||
+ | <syntaxhighlight2 lang="cpp"> | ||
+ | virtual void mfVirtual_vDispValue() = 0; | ||
+ | </syntaxhighlight2> | ||
+ | |||
+ | とすることで、基底クラスに純粋仮想関数が定義され、抽象クラスになったと言えます。本来の意味としては、派生クラスに全部任せるから、基底クラスを直接利用されないようにmf_vBaseDispValue()はprotectedに移動させておきました。サンプルなので、そこまでする必要もないし、あんまり有意義でもないですが、カッコだけはつけておきました。 | ||
+ | |||
+ | |||
+ | それだけではまずくて、プログラム部も以下のように、mfVirtual_vDispValue()のプログラム部分を消す必要があります。 | ||
+ | |||
+ | <span style="color: #ffffff; background-color: #555555; padding: 0px 5px 0px 5px; display: inline-block;">cpp <span>(</span>基底クラス BaseInheritance.cpp<span>)</span><!-- padding 上 右 下 左--> | ||
+ | <syntaxhighlight2 lang="cpp" line start=201> | ||
+ | #include "pch.h" | ||
+ | #include "BaseInheritance.h" | ||
+ | |||
+ | CBaseInheritance::CBaseInheritance() { | ||
+ | printf("Constructor:CBaseInheritance()\n"); | ||
+ | } | ||
+ | |||
+ | CBaseInheritance::CBaseInheritance(int iArgBaseMoney, int iArgBaseMonth) | ||
+ | :m_iBaseMoney(iArgBaseMoney) | ||
+ | ,m_iBaseMonth(iArgBaseMonth) | ||
+ | ,m_iMoney(0) { | ||
+ | printf("Constructor:CBaseInheritance(int,int)\n"); | ||
+ | } | ||
+ | |||
+ | CBaseInheritance::~CBaseInheritance() { | ||
+ | printf("Destructor:~CBaseInheritance()\n"); | ||
+ | } | ||
+ | |||
+ | int CBaseInheritance::mf_iBaseSumMoney() { | ||
+ | m_iMoney = m_iBaseMoney * m_iBaseMonth; | ||
+ | return m_iMoney; | ||
+ | } | ||
+ | |||
+ | void CBaseInheritance::mf_vBaseDispValue() { | ||
+ | int iSumMoney = m_iBaseMoney * m_iBaseMonth; | ||
+ | printf("BaseMoney=%d, total=%d\n", iSumMoney, m_iMoney); | ||
+ | } | ||
+ | </syntaxhighlight2> | ||
+ | |||
+ | |||
+ | このように、まるまるプログラム部分を削りました。このサンプルではプロジェクトからCDeriveArrInheritanceとCDeriveDiscountInheritanceを除外しています。 | ||
+ | |||
+ | |||
+ | で動かすと | ||
+ | |||
+ | <span style="color: #ffffff; background-color: #555555; padding: 0px 5px 0px 5px; display: inline-block;">実行結果<!-- padding 上 右 下 左--> | ||
+ | <syntaxhighlight2 lang="text" line start=701> | ||
+ | Constructor:CBaseInheritance(int,int) | ||
+ | Constructor:CDriveInheritance(int,int,int) | ||
+ | BaseMoney=22800, OptionMoney=600 total=23400 | ||
+ | Constructor:CBaseInheritance(int,int) | ||
+ | Constructor:CDriveInheritance(int,int,int) | ||
+ | BaseMoney=22800, OptionMoney=600 total=23400 | ||
+ | Destructor:~CBaseInheritance() | ||
+ | Destructor:~CDriveInheritance() | ||
+ | Destructor:~CBaseInheritance() | ||
+ | </syntaxhighlight2> | ||
+ | |||
+ | |||
+ | と問題なく動作します。 | ||
[[C PlusPlus#C++からの技術|C++]]に戻る | [[C PlusPlus#C++からの技術|C++]]に戻る |