Cpp クラス 継承 アップキャスト 新しいページはコチラ
提供: yonewiki
(→クラス 継承 アップキャスト) |
|||
| 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> | ||
| 66行: | 66行: | ||
<span style="color: #ffffff; background-color: #555555; padding: 0px 5px 0px 5px; display: inline-block;">cpp <span>(</span>基底クラス BaseInheritance.cpp<span>)</span><!-- padding 上 右 下 左--> | <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> | + | <syntaxhighlight2 lang="cpp" line start=100> |
#include "pch.h" | #include "pch.h" | ||
#include "BaseInheritance.h" | #include "BaseInheritance.h" | ||
| 92行: | 92行: | ||
void CBaseInheritance::mf_vDispValue() { | void CBaseInheritance::mf_vDispValue() { | ||
int iSumMoney = mf_iBaseSumMoney(); | int iSumMoney = mf_iBaseSumMoney(); | ||
| − | printf("BaseMoney=%d\n", iSumMoney); | + | printf("BaseMoney=%d total=%d\n", iSumMoney, m_iMoney); |
} | } | ||
| 107行: | 107行: | ||
<span style="color: #ffffff; background-color: #555555; padding: 0px 5px 0px 5px; display: inline-block;">cpp <span>(</span>派生クラス DeriveInheritance.h<span>)</span><!-- padding 上 右 下 左--> | <span style="color: #ffffff; background-color: #555555; padding: 0px 5px 0px 5px; display: inline-block;">cpp <span>(</span>派生クラス DeriveInheritance.h<span>)</span><!-- padding 上 右 下 左--> | ||
| − | <syntaxhighlight2 lang="cpp" line> | + | <syntaxhighlight2 lang="cpp" line start=200> |
#ifndef __DERIVEINHERITANCE_H_YONET__ | #ifndef __DERIVEINHERITANCE_H_YONET__ | ||
#define __DERIVEINHERITANCE_H_YONET__ | #define __DERIVEINHERITANCE_H_YONET__ | ||
| 132行: | 132行: | ||
<span style="color: #ffffff; background-color: #555555; padding: 0px 5px 0px 5px; display: inline-block;">cpp <span>(</span>派生クラス DeriveInheritance.cpp<span>)</span><!-- padding 上 右 下 左--> | <span style="color: #ffffff; background-color: #555555; padding: 0px 5px 0px 5px; display: inline-block;">cpp <span>(</span>派生クラス DeriveInheritance.cpp<span>)</span><!-- padding 上 右 下 左--> | ||
| − | <syntaxhighlight2 lang="cpp" line> | + | <syntaxhighlight2 lang="cpp" line start=300> |
#include "pch.h" | #include "pch.h" | ||
#include "DeriveInheritance.h" | #include "DeriveInheritance.h" | ||
| 147行: | 147行: | ||
m_iDeriveOption = iArgOption; | m_iDeriveOption = iArgOption; | ||
| + | m_iMoney = mf_iBaseSumMoney() + m_iDeriveOption; | ||
} | } | ||
| 182行: | 183行: | ||
<span style="color: #ffffff; background-color: #555555; padding: 0px 5px 0px 5px; display: inline-block;">cpp <span>(</span>配列入力の派生クラス DeriveArrInheritance.h<span>)</span><!-- padding 上 右 下 左--> | <span style="color: #ffffff; background-color: #555555; padding: 0px 5px 0px 5px; display: inline-block;">cpp <span>(</span>配列入力の派生クラス DeriveArrInheritance.h<span>)</span><!-- padding 上 右 下 左--> | ||
| − | <syntaxhighlight2 lang="cpp" line> | + | <syntaxhighlight2 lang="cpp" line start=400> |
#ifndef __DERIVEARRINHERITANCE_H_YONET__ | #ifndef __DERIVEARRINHERITANCE_H_YONET__ | ||
#define __DERIVEARRINHERITANCE_H_YONET__ | #define __DERIVEARRINHERITANCE_H_YONET__ | ||
| 210行: | 211行: | ||
<span style="color: #ffffff; background-color: #555555; padding: 0px 5px 0px 5px; display: inline-block;">cpp <span>(</span>配列入力の派生クラス DeriveArrInheritance.cpp<span>)</span><!-- padding 上 右 下 左--> | <span style="color: #ffffff; background-color: #555555; padding: 0px 5px 0px 5px; display: inline-block;">cpp <span>(</span>配列入力の派生クラス DeriveArrInheritance.cpp<span>)</span><!-- padding 上 右 下 左--> | ||
| − | <syntaxhighlight2 lang="cpp" line> | + | <syntaxhighlight2 lang="cpp" line start=500> |
#include "pch.h" | #include "pch.h" | ||
#include "DeriveArrInheritance.h" | #include "DeriveArrInheritance.h" | ||
| 269行: | 270行: | ||
<span style="color: #ffffff; background-color: #555555; padding: 0px 5px 0px 5px; display: inline-block;">cpp <span>(</span>割引の派生クラス DeriveDiscountInheritance.h<span>)</span><!-- padding 上 右 下 左--> | <span style="color: #ffffff; background-color: #555555; padding: 0px 5px 0px 5px; display: inline-block;">cpp <span>(</span>割引の派生クラス DeriveDiscountInheritance.h<span>)</span><!-- padding 上 右 下 左--> | ||
| − | <syntaxhighlight2 lang="cpp" line> | + | <syntaxhighlight2 lang="cpp" line start=600> |
#ifndef __DERIVEDISCOUNTINHERITANCE_H_YONET__ | #ifndef __DERIVEDISCOUNTINHERITANCE_H_YONET__ | ||
#define __DERIVEDISCOUNTINHERITANCE_H_YONET__ | #define __DERIVEDISCOUNTINHERITANCE_H_YONET__ | ||
| 295行: | 296行: | ||
<span style="color: #ffffff; background-color: #555555; padding: 0px 5px 0px 5px; display: inline-block;">cpp <span>(</span>割引の派生クラス DeriveDiscountInheritance.cpp<span>)</span><!-- padding 上 右 下 左--> | <span style="color: #ffffff; background-color: #555555; padding: 0px 5px 0px 5px; display: inline-block;">cpp <span>(</span>割引の派生クラス DeriveDiscountInheritance.cpp<span>)</span><!-- padding 上 右 下 左--> | ||
| − | <syntaxhighlight2 lang="cpp" line> | + | <syntaxhighlight2 lang="cpp" line start=700> |
#include "pch.h" | #include "pch.h" | ||
#include "DeriveDiscountInheritance.h" | #include "DeriveDiscountInheritance.h" | ||
| 338行: | 339行: | ||
<span style="color: #ffffff; background-color: #555555; padding: 0px 5px 0px 5px; display: inline-block;">cpp <span>(</span>メイン関数 InheritanceMain.cpp<span>)</span><!-- padding 上 右 下 左--> | <span style="color: #ffffff; background-color: #555555; padding: 0px 5px 0px 5px; display: inline-block;">cpp <span>(</span>メイン関数 InheritanceMain.cpp<span>)</span><!-- padding 上 右 下 左--> | ||
| − | <syntaxhighlight2 lang="cpp" line> | + | <syntaxhighlight2 lang="cpp" line start=800> |
#include "pch.h" | #include "pch.h" | ||
#include "BaseInheritance.h" | #include "BaseInheritance.h" | ||
| 348行: | 349行: | ||
CBaseInheritance objCBaseInheritance(3900, 12); | CBaseInheritance objCBaseInheritance(3900, 12); | ||
| − | objCBaseInheritance. | + | objCBaseInheritance.mf_vDispValue(); |
CDeriveInheritance objCDeriveInheritance2Arg(2900, 12); | CDeriveInheritance objCDeriveInheritance2Arg(2900, 12); | ||
objCDeriveInheritance2Arg.mf_vDeriveSetOptionValue(600); | objCDeriveInheritance2Arg.mf_vDeriveSetOptionValue(600); | ||
| − | objCDeriveInheritance2Arg. | + | objCDeriveInheritance2Arg.mf_vDispValue(); |
CDeriveInheritance objCDeriveInheritance3Arg(2900, 12, 600); | CDeriveInheritance objCDeriveInheritance3Arg(2900, 12, 600); | ||
| − | objCDeriveInheritance3Arg. | + | objCDeriveInheritance3Arg.mf_vDispValue(); |
int piOptionArr[] = { 300, 500, 400, 390 }; | int piOptionArr[] = { 300, 500, 400, 390 }; | ||
int iSize = (int)(sizeof piOptionArr / sizeof(*piOptionArr)); | int iSize = (int)(sizeof piOptionArr / sizeof(*piOptionArr)); | ||
CDeriveArrInheritance objCDeriveArrInheritance(3900, 12, piOptionArr, iSize); | CDeriveArrInheritance objCDeriveArrInheritance(3900, 12, piOptionArr, iSize); | ||
| − | objCDeriveArrInheritance. | + | objCDeriveArrInheritance.mf_vDispValue()(); |
CDeriveDiscountInheritance objCDeriveDiscountInheritance(3900, 12, 0.5); | CDeriveDiscountInheritance objCDeriveDiscountInheritance(3900, 12, 0.5); | ||
| − | objCDeriveDiscountInheritance. | + | objCDeriveDiscountInheritance.mf_vDispValue(); |
return 0; | return 0; | ||
| 369行: | 370行: | ||
} | } | ||
</syntaxhighlight2> | </syntaxhighlight2> | ||
| + | |||
| + | アップキャストの話をしている現段階では、上記のメイン関数は普通に派生クラスを使っているだけなので、特に説明もいらないでしょう。基底クラス→一つしかオプション価格を受け取らない派生クラス→複数のオプション価格をうけとる配列を扱う派生クラス→割引を扱う派生クラスの順に動かしています。動かした結果は以下のとおりです。 | ||
| + | |||
| + | <span style="color: #ffffff; background-color: #555555; padding: 0px 5px 0px 5px; display: inline-block;">実行結果<!-- padding 上 右 下 左--> | ||
| + | <syntaxhighlight2 lang="text" line start=900> | ||
| + | Constructor:CBaseInheritance(int,int) | ||
| + | BaseMoney=46800, total=35700 | ||
| + | Constructor:CBaseInheritance(int,int) | ||
| + | Constructor:CDriveInheritance(int,int) | ||
| + | BaseMoney=34800, total=35700 | ||
| + | Constructor:CBaseInheritance(int,int) | ||
| + | Constructer:CDeriveInheritance(int,int,int) | ||
| + | BaseMoney=34800, total=35700 | ||
| + | Constructor:CBaseInheritance(int,int) | ||
| + | Constructer:CDeriveArrInheritance(int,int,int*,int) | ||
| + | BaseMoney=46800, total=48390 | ||
| + | Constructor:CBaseInheritance(int,int) | ||
| + | Constructer:CDeriveDiscountInheritance(int,int,double) | ||
| + | BaseMoney=46800, total=23400 | ||
| + | Destructer:~CDeriveDiscountInheritance() | ||
| + | Destructor:~CBaseInheritance() | ||
| + | Destructer:~CDeriveArrInheritance() | ||
| + | Destructor:~CBaseInheritance() | ||
| + | Destructer:~CDeriveInheritance() | ||
| + | Destructor:~CBaseInheritance() | ||
| + | Destructer:~CDeriveInheritance() | ||
| + | Destructor:~CBaseInheritance() | ||
| + | Destructor:~CBaseInheritance() | ||
| + | </syntaxhighlight2> | ||
| + | |||
| + | コンストラクタとデストラクタがどういう風に動作するのかがわかるように呼び出されたら、printfで何が呼ばれたかわかるようにしています。勝手に呼ばれることも多いので、わかりやすいです。 | ||
| + | |||
| + | |||
| + | で、これを元にアップキャストって奴をやってみようと思います。こんな行き当たりばったりでサンプルを作っているので、上手いこと行くかはわかりませんが、メイン関数を作り直してみます。 | ||
| + | |||
| + | <span style="color: #ffffff; background-color: #555555; padding: 0px 5px 0px 5px; display: inline-block;">cpp <span>(</span>メイン関数 InheritanceMain.cpp<span>)</span><!-- padding 上 右 下 左--> | ||
| + | <syntaxhighlight2 lang="cpp" line start=1000> | ||
| + | #include "pch.h" | ||
| + | #include "BaseInheritance.h" | ||
| + | #include "DeriveInheritance.h" | ||
| + | #include "DeriveArrInheritance.h" | ||
| + | #include "DeriveDiscountInheritance.h" | ||
| + | |||
| + | CBaseInheritance* pCBaseInheritanceUpcastF(int iSelectDerive) { | ||
| + | int piOptionUpcastArr[] = { 800, 200, 500, 220 }; | ||
| + | int iSize = (int)(sizeof piOptionUpcastArr / sizeof(*piOptionUpcastArr)); | ||
| + | switch (iSelectDerive) { | ||
| + | case 1: | ||
| + | return new CDeriveInheritance(2900, 12); | ||
| + | case 2: | ||
| + | return new CDeriveArrInheritance(2900, 12, piOptionUpcastArr, iSize); | ||
| + | default: | ||
| + | return new CDeriveDiscountInheritance(3900, 12, 0.5); | ||
| + | } | ||
| + | }; | ||
| + | |||
| + | int main() { | ||
| + | |||
| + | CBaseInheritance* pCBaseInheritanceUpcast; | ||
| + | pCBaseInheritanceUpcast = pCBaseInheritanceUpcastF(1); | ||
| + | pCBaseInheritanceUpcast->mf_vDispValue(); | ||
| + | pCBaseInheritanceUpcast = pCBaseInheritanceUpcastF(2); | ||
| + | pCBaseInheritanceUpcast->mf_vDispValue(); | ||
| + | pCBaseInheritanceUpcast = pCBaseInheritanceUpcastF(3); | ||
| + | pCBaseInheritanceUpcast->mf_vDispValue(); | ||
| + | delete pCBaseInheritanceUpcast; | ||
| + | |||
| + | return 0; | ||
| + | |||
| + | } | ||
| + | </syntaxhighlight2> | ||
| + | |||
| + | このようにサンプルのメインプログラムだけを変えました。基底クラスのポインタ変数を作って、派生クラスを動かした結果を受け取っています。プログラムの中で、動かす派生クラスを選べて、基底クラスを利用するカタチにしてみました。派生クラスを生成するとオブジェクトが出来当たりますが、そのオブジェクトのポインタを返却(return)したときに関数の返却値の型が基底クラスのポインタ型になっています。そして、結果をそのままメイン関数で受け取るので、アップキャストはreturnの型から返却値の型に変換されているところで起こっています。 | ||
| + | |||
| + | |||
| + | 実行した結果は以下のようになります。 | ||
| + | |||
| + | |||
| + | <span style="color: #ffffff; background-color: #555555; padding: 0px 5px 0px 5px; display: inline-block;">実行結果<!-- padding 上 右 下 左--> | ||
| + | <syntaxhighlight2 lang="text" line start=1100> | ||
| + | Constructor:CBaseInheritance(int,int) | ||
| + | Constructor:CDriveInheritance(int,int) | ||
| + | BaseMoney=34800, total=35700 | ||
| + | Constructor:CBaseInheritance(int,int) | ||
| + | Constructer:CDeriveArrInheritance(int,int,int*,int) | ||
| + | BaseMoney=34800, total=36520 | ||
| + | Constructor:CBaseInheritance(int,int) | ||
| + | Constructer:CDeriveDiscountInheritance(int,int,double) | ||
| + | BaseMoney=46800, total=23400 | ||
| + | Destructor:~CBaseInheritance() | ||
| + | </syntaxhighlight2> | ||
| + | |||
| + | |||
| + | ちゃんとアップキャストされても、ちゃんと基底クラスのメンバ関数が派生クラスで動作した内容を反映して動いています。でもデストラクタは、呼ばれていないですね。残念なプログラムになっているようです。次の「継承 デストラクタ」の記事でこの問題について対応したいと思います。今のままでは動的に変数をクラス内で生成しているCDeriveArrInheritanceを使ったときにメモリリークが起こってしまいます。動的に確保したint型の配列メモリをプログラム終了後も解放しようとしない現象です。実際にはプログラム終了時にRAII(Resource Acquisition Is Initialization)という機能によって、ほとんどの場合メモリは解放されます。C++では、smart pointerというものに包み込まれた状態になり、動的に確保したメモリ領域を監視しているので、動的に確保されたメモリは適切に開放されます。たとえ途中で例外処理が発生してプログラムが落っこちた場合でも、解放されます。でも、ちゃんとやった方がいいです。上記のような状態は決してメモリリークがおきないとは保証されないので、ちゃんとやった方がいいのです。でも、アップキャストしたら元々のデストラクタが呼ばれないのは困ったものです。うっかりすると危険だわ。 | ||
[[C PlusPlus#C++からの技術|C++]]に戻る | [[C PlusPlus#C++からの技術|C++]]に戻る | ||