第 8 章: 継承

継承とは

継承 (インヘリタンス)は, あるクラスのメンバを, 他のクラスに引き継ぐ (継承させる) という効果がある.

継承のコーディング例

C++ では継承を実現するために, 次のようにコーディングする:

// 継承元のクラス定義
class CBase{
private:
  int m_num;

public:
  void PrintNum();
};

// 継承を行うクラス定義
// CBase クラスを継承
class CSub : public CBase{
public:
  void Func();
};

継承を行ったことにより, 次のように PrintNum メンバ関すを呼び出せる:

int main(){
  CSub sub; // CSub クラスのインスタンス化

  sub.PrintNum(); // CBase クラスのメンバ関数を呼び出す
  return 0;
}

注意:

サブクラスのインスタンスから, スーパークラスのメンバにアクセスするには, そのメンバが public である必要がある. private なメンバにはアクセスできない.

継承の例

例えば, 画面に線を描くプログラムを作ることを考えて, ペンをクラスで実現する.

まず, よく使う黒い線を引くために CPen クラスを用意する.

そして, それを継承して, 好きな色の線を描く CColorPen クラスを用意する:

// 基本となるペンクラス
class CPen{
public:
  void DrawLine(int sx, int sy, int ex, int ey);
};

// 色ペンクラス
class CColorPen : public CPen{
  // メンバは省略
};

継承した場合のコンストラクタとデストラクタ

class.h

class.cpp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// class.cpp
#include <iostream>
#include "class.h"

CBase::CBase(){
  std::cout << "CBase クラスのコンストラクタが呼び出された" << std::endl;
}

CBase::~CBase(){
  std::cout << "CBase クラスのデストラクタが呼び出された" << std::endl;
}

CSub::CSub(){
  std::cout << "CSub クラスのコンストラクタが呼び出された" << std::endl;
}

CSub::~CSub(){
  std::cout << "CSub クラスのデストラクタが呼び出された" << std::endl;
}

main.cpp

1
2
3
4
5
6
7
8
// main.cpp
#include "class.h"

int main(){
  CSub sub; // サブクラスをインスタンス化

  return 0;
}

GNUmakefile

.SUFFIXES: .o .cpp
.cpp.o:
	$(CC) -c $(CFLAGS) $<

PROG = main
CC = g++
CFLAGS = -g -Wall
SRC = class.cpp main.cpp
OBJ = class.o main.o

hist: $(OBJ)
	$(CC) $(CFLAGS) -o $(PROG) $(OBJ)

.PHONY: clean
clean:
	$(RM) $(PROG) $(OBJ) *~ a.out

main.o: class.h main.cpp
class.o: class.h class.cpp

上記プログラムの実行結果は:

[wtopia subclass]$ make
g++ -c -g -Wall class.cpp
g++ -c -g -Wall main.cpp
g++ -g -Wall -o main class.o main.o
[wtopia subclass]$ ./main
CBase クラスのコンストラクタが呼び出された
CSub クラスのコンストラクタが呼び出された
CSub クラスのデストラクタが呼び出された
CBase クラスのデストラクタが呼び出された