>  > アドミレイション アルタモーダ フロアマット エレガンスチェック GFWN11A ニッサン ウイングロード Y11 1999年05月~

ニッサン 1999年05月~ GFWN11A ニッサン アドミレイション ウイングロード アルタモーダ フロアマット エレガンスチェック Y11 GFWN11A

継承の概念

C++言語に限らず、オブジェクト指向言語に備わっている重要な特性の1つに継承(インヘリタンス)が あります。継承は、あるクラスのメンバを、他のクラスに引継ぐ(継承させる)という効果があります。

では、実際に継承とはどういうものか、さらに詳しく説明しましょう。すでに述べたように、クラスは、インスタンス、およびオブジェクトの「設計図」です。自動車の例を出すのならば、自動車の設計図がクラス、実際に工場で生産された自動車本体が、インスタンス、およびオブジェクトということになります。

親クラスと子クラス

ところで、自動車といえば、通常は乗用車を想像してしまうかもしれませんが、実際、自動車と呼ばれるものは実に多種多様です。たとえば、車両であるパトロールカー、荷物を運ぶトラック、さらには緊急車両であるトラックなどなど、実に多種多様な種類が存在します。それらは、「自動車」でありながら、それぞれ機能に応じた独自の機能の拡張がなされています。

図6-1:継承のイメージ

このように、基本となるクラスの性質を受け継ぎ、独自の拡張をすることを、オブジェクト指向では、継承(けいしょう)と呼びます。継承のもととなるクラスのことを、親クラス,スーパークラスなどと呼びます。それにたいし、親クラスの機能を継承し、独自の機能を実装したクラスのことを、子クラス、もしくは、サブクラスと呼びます。

前述の自動車の例で言うのならば、車クラスが親クラス、トラックや救急車などが、サブクラスということになります。(図6-1.参照)

継承の実装

では実際に、この継承を実装してみましょう。ここでは、前述の、自動車と、救急車の例をプログラムにしてみます。少し長いですが、

アドミレイション アルタモーダ フロアマット エレガンスチェック GFWN11A ニッサン ウイングロード Y11 1999年05月~

【USA在庫あり】 コロニー Colony Machine ヘッド ボルト キット 48年-84年 BigTwin クローム 10個入り 043999 HD, NISSAN(ニッサン) 日産純正部品 カバー、フロントアンダ- 82001-66452, 柿本改(カキモト) マフラー ホンダ オデッセイ ClassKR 13/11~ オデッセイ アブソルート EX DBA-RC1, 17インチエスティマ50系 2WDENKEI パフォーマンスライン PF01 スパークルシルバー 7.0Jx17Bluearth RV-02 215/55R17, NARDI ステアリング トヨタ アバロン CX10 7/6~ FET BOSS KIT(FET ボスキット)・NARDI(ナルディ) ステアリングセット ステアリングボス BOSS〔FB536〕/ステアリング〔N750〕 17インチ サマータイヤ セット【適応車種:プリウスα(40系 全グレード)】WORK エモーション M8R アッシュドチタン 7.0Jx17VEURO VE303 215/50R17, HONDA ホンダ NWGN N-WGN エヌワゴン ホンダ純正 オートリトラミラー 2016.6~次モデル 08V02-T6G-000 , 【ツイン ストラットバー】EC22S フロントストラットバー typeSTD カワイワークス (SZ0550-FTS-00, 【S610】MRワゴン [H13/12-H16/2][MF21S] カジュアル Bellezza ベレッツァシートカバー, 【ポイント5倍 1/7~順次対応】 オンダッシュモニター10.1インチHDMI2WAYヘッドレスト固定用ブラケット付12Vシガーソケット電源USBスマホiPhoneAndroid_43138 NOKIAN Hakkapeliitta R3 SUV 235/50R19 (ノキアン ハッカペリッタ R3 SUV) 新品タイヤ 4本価格

アドミレイション アルタモーダ フロアマット エレガンスチェック GFWN11A ニッサン ウイングロード Y11 1999年05月~:IMPUL S15 シルビア 315S フロントバンパー 185/60R15 84H DUNLOP ダンロップ ENASAVE RV504 エナセーブ RV504 TRG-GB10 TRG GB10 サマータイヤホイール4本セット

アドミレイション アルタモーダ フロアマット エレガンスチェック GFWN11A ニッサン ウイングロード Y11 1999年05月~.LEDルームランプ PMC850 ホワイト 白色系 ボルボ XC70 2008年以降 送料無料(一部離島除く) RS-R アールエスアール車高調 ベストi トヨタ アルファード(2015~2018 30系 AGH35W) フジコーポレーション

【送料無料】 215/45R17 17インチ LEHRMEISTER レアマイスター ブルネッロ(ブラック/リムポリッシュ) 7J 7.00-17 FALKEN ファルケン アゼニス FK510 サマータイヤ ホイール4本セット フジコーポレーション HKS 大容量フューエルポンプ 1407-RN019 ニッサン スカイラインGT-R BCNR33 RB26DETT 1995年01月~1998年12月

、以下のプログラムを実行してみてください。

list6-1:car.h
#ifndef _CAR_H_
#define _CAR_H_
// 自動車クラス
class CCar{
public:
 // コンストラクタ
 CCar();
 // デストラクタ
 virtual ~CCar();
 // 移動メソッド
 void move();
 // 燃料補給メソッド
 void supply(int fuel);
private:
 int m_fuel; // 燃料
 int m_migration; // 移動距離
};
#endif // _CAR_H_
car.cpp
#include "car.h"
#include <iostream>
using namespace std;
// コンストラクタ
CCar::CCar() : m_fuel(0),m_migration(0)
{
 cout < "ccarオブジェクト生成"="">< endl;="" }="" デストラクタ="" ccar::~ccar()="" {="" cout="">< "ccarオブジェクト破棄"="">< endl;="" }="" void="" ccar::move()="" {="" 燃料があるなら移動="" if(m_fuel="">= 0){
 m_migration++; // 距離移動
 m_fuel--; // 燃料消費
 }
 cout < "移動距離:"="">< m_migration="">< endl;="" cout="">< "燃料"="">< m_fuel="">< endl;="" }="" 燃料補給メソッド="" void="" ccar::supply(int="" fuel)="" {="" if(fuel=""> 0){
 m_fuel += fuel; // 燃料補給
 }
 cout < "燃料"="">< m_fuel="">< endl;="" }="">
ambulance.h
#ifndef _AMBULANCE_H_
#define _AMBULANCE_H_
#include "car.h"
class CAmbulance : public CCar{
public:
//コンストラクタ
CAmbulance();
// デストラクタ
virtual ~CAmbulance();
// 救急救命活動
void sevePeople();
private:
int m_number;
};
#endif // _AMBULANCE_H_
ambulance.cpp
#include "ambulance.h"
#include <iostream>
using namespace std;
// コンストラクタ
CAmbulance::CAmbulance() : m_number(119)
{
cout < "cambulanceオブジェクト生成"="">< endl;="" }="" デストラクタ="" cambulance::~cambulance()="" {="" cout="">< "cambulanceオブジェクト破棄"="">< endl;="" }="" 救急救命活動="" void="" cambulance::sevepeople(){="" cout="">< "救急救命活動"="">< endl="">< "呼び出しは"="">< m_number="">< "番"="">< endl;="" }="">
main.cpp
#include "car.h"
#include "ambulance.h"
int main() {
 CCar c;
 c.supply(10); // 燃料補給
 c.move(); // 移動
 c.move(); // 移動
CAmbulance a;
a.supply(10);
a.move();
a.sevePeople();
 return 0;
}
実行結果
CCarオブジェクト生成
燃料10
移動距離:1
燃料9
移動距離:2
燃料8
CCarオブジェクト生成
CAmbulanceオブジェクト生成
燃料10
移動距離:1
燃料9
救急救命活動
呼び出しは119番
CAmbulanceオブジェクト破棄
CCarオブジェクト破棄
CCarオブジェクト破棄

あるクラスが、別のクラスを親クラスとするときの定義は、

親クラスを継承した、子クラスの定義の方法
class 子クラス名 : public 親クラス名

のように定義します。つまり、CAmbulanceクラスは、CCarクラスを継承したクラスです。そのため、CCarクラスが親クラス、CAmbulanceクラスが、子クラスという組み合わせになります。なお、ambulanceとは、英語で救急車を表す言葉であり、このクラスは、「救急車クラス」ということになります。

このことから、publicメンバである、move()メソッド、および、supply()メソッドを利用することができます。ただ、CCarクラスのprivateメンバ変数である 【ブリッド】ミラ [LA275] 2WD AT リアヒーター有 (H23/7月以降(後期)) 【フロントのみ】、m_fuelおよび、m_migrationには、直接アクセスすることはできません。

また、CAmbulanceクラスは、さらに独自のメンバである、メンバ変数のm_number 【S606】ワゴンR [H20/9-H24/5][MH23S] ワイルドステッチ ライトベージュxホワイト Bellezza ベレッツァ シートカバー エスティマ GSR50W(3.5L 2WD)/ACR50W(2.4L 2WD) KBマフラーシリーズ KB-SNIPER(ケービー・スナイパー) 【ハーフステン/片出し】 K-BREAK/ケイブレイク、および プロジェクトμ ベストップ フロント左右セット ブレーキパッド オーパ ACT10 F128 プロジェクトミュー プロミュー プロμ BESTOP ブレーキパット【店頭受取対応商品】、savePeopleメソッドは、CAmbulanceクラスで利用することができますが、CCarクラスでは利用することはできません。

サブクラスのコンストラクタとデストラクタ

次に、子クラスのコンストラクタとデストラクタの組み合わせについて注目してみましょう。プログラムをみてもわかるとおり、この子クラスにも、親クラスと同様に、コンストラクタ(CAmbulance)および、デストラクタ(~CAmbulance)が定義されています。

また、実行結果からもわかるとおり、実はサブクラスが生成される際、子クラスのコンストラクタが実行される前に、親クラスのコンストラクタが実行され、逆にdeleteでインスタンスが破棄されるときは、子クラスのデストラクタが実行され、そのあと親クラスのデストラクタが実行されることがわかります。

このように、継承が利用された場合、親クラスのコンストラクタ・デストラクタも利用されることがわかります。

図6-2:CCarクラスとCAmbulanceクラスのコンストラクタ・デストラクタの呼び出し順

なお、CCarおよび、CAmbulanceクラスについている パナソニック コスモシリーズプレート用継枠(ホワイト) WT8172W20 住宅・配線・電設資材 20個、virtual(バーチャル)修飾子に関しては、必ずつけるようにしてください。通常、C++言語では、継承を用いる場合、virtualをデストラクタにつけるように推奨されています。理由は難しいのでここでは省略しますが、どのようなクラスでも、そのサブクラスが作られる可能性があるので、今後、基本的にクラスのコンストラクタには、virtualをつけるようにしましょう。

UML

UMLクラス図による表記

なお、プログラムの動作には直接関係はありませんが、ここでC++に限らず、オブジェクト指向言語の設計に用いられる、UMLというツールの中にある、クラス図を用いて、このクラスでこのクラスを表記してみることにします。

まず、クラス図ですが、クラスを以下のような方法で表記します。(図6-3.参照)

図6-3:UMLのクラス図における、クラスの表記方法

このように、3つに区切られた四角形の中に、上からクラス名メンバ変数(属性)メンバ関数(操作)を記入します。(クラス名以外は省略可能)複数のクラスが存在する場合には、これにさらにクラス間の関係性が記入されます。また、メンバ変数およびメンバ関数の前には、+-#といった記号を記述します。これらはそれぞれ、publicprivateprotectedを表します。

このようにして、クラスを表記し、さらに、クラス間の関係性を表記することも可能です。継承もその関係性の一つです。実際にCCarクラスと、CAmbulanceクラスを用いて表記すると 、以下のようになります。(図6-4.参照)

図6-4:CCarクラスとCAmbulanceクラスを例に、クラス図の継承を表記

図のように、UMLのクラス図で継承を表記する場合親クラスと子クラスの間の間を△のついた線で結びます。△の上には親クラス(スーパークラス)、下には子クラス(サブクラス)がきます。

protectedメンバ

すでに学んだとおり、privateメンバは、同一クラス内から、publicメンバは、クラス内・外を問わず、アクセスすることができます。しかし、三つ目のprotectedについては、詳しく説明してきませんでしたので、この場で詳しく説明します。

list6-2:Vector2D.h
#ifndef _VECTOR2D_H_
#define _VECTOR2D_H_
//二次元ベクトルクラス
class Vector2D{
protected:
int m_x;
int m_y;
public:
//コンストラクタ
Vector2D();
//値の設定
void setValue(int x,int y);
//X座標の取得
int getX();
//Y座標の取得
int getY();
protected:
//初期化
void init();
};
#endif // _VECTOR2D_H_
Vectro2D.cpp
#include "Vector2D.h"
//コンストラクタ
Vector2D::Vector2D()
{
init();
}
//値の設定
void Vector2D::setValue(int x,int y)
{
m_x = x; m_y = y;
}
//X座標の取得
int Vector2D::getX()
{
return m_x;
}
//Y座標の取得
int Vector2D::getY()
{
return m_y;
}
void Vector2D::init()
{
m_x = 0; m_y = 0;
}
Position2D.h
#ifndef _POSITION2D_H_
#define _POSITION2D_H_
#include "Vector2D.h"
class Position2D : public Vector2D{
public:
//位置のリセット
void resetPosition();
//移動
void move(int dx,int dy);
};
#endif // _POSITION2D_H_
Position2D.cpp
#include "Position2D.h"
void Position2D::resetPosition(){
init();
}
void Position2D::move(int dx,int dy)
{
m_x += dx;
m_y += dy;
}
main.cpp
#include "Position2D.h"
#include <iostream>
using namespace std;
int main(int argc,char** args) {
Position2D p;
p.setValue(1,1);
p.move(2,3);
cout < "p:("="">< p.getx()="">< ","="">< p.gety()="">< ")"="">< endl;="" p.resetposition();="" cout="">< "p:("="">< p.getx()="">< ","="">< p.gety()="">< ")"="">< endl;="" return="" 0;="" }="">
実行結果
p:(3,4)
p:(0,0)

Point2Dクラスは、Vector2Dクラスを継承しています。そのため、親クラスのpublicなメンバである、setValue(),getX(),getY()関数を利用できます。また、Vector2Dで定義されているメンバ変数のm_xm_yおよび、メンバ関数init()にも、クラス内からアクセスすることが可能です。

ただ、protectedメンバは、privateメンバ同様、クラス外からのアクセスはできません。つまり、protectedメンバは、子クラスから見ればpublicとように、クラス外から見ればprivateのようにふるまうことができるのです。このように、サブクラスのみにアクセスを許すメンバには、protected修飾子をつけます(図6-5.参照)。

図6-5:protectedメンバへのアクセス

多重継承

単一継承と多重継承

ここまで、C++言語の継承について説明してきましたが、今までの例では、親クラスが一つしか存在しませんでした。このように、親クラスが一つしかないような継承の仕方を、単一継承(たんいつけいしょう)と言います。ただ、C++では、ひとつのクラスに複数の親クラスを設定することができます。これを、多重継承(たじゅうけいしょう)と言います。(図6-6.参照)

図6-6:単一継承と他重継承(クラス図で表記)

現在用いられているオブジェクト指向言語は、Java,C#など様々ですが、基本的に多重継承を許しているのはC++のみです。

多重継承の実装

では、C++で多重継承を実装するにはどのようにすればよいのでしょうか?そのやり方は、簡単で、以下のような記述方法になります。そのため、現在では、純粋仮想クラスなどのように、多言語のインターフェースに類するような特殊なクラスの継承に用いられるのがほとんどです。なので、基本的に継承を用いる際には、原則的に子クラスは親クラスを原則一つしか持たないようにするように心掛けましょう。

class Sub : public SupA,public SupB{

}

このように、継承する親クラスの間を、,(コンマ)で区切れば、複数の親クラスを持つことが可能です。ただ、多重継承を用いるのは、技術的な問題点も多く、

アドミレイション アルタモーダ フロアマット エレガンスチェック GFWN11A ニッサン ウイングロード Y11 1999年05月~

、あまり推奨されていません。

練習問題 : 問題6.


{yahoojp}jpprem01-zenjp40-wl-zd-57480