第 11 章: オーバーロード

オーバーロード

オーバーロードは, 同じ名前のメンバ関数を複数定義できる.

オーバーロードの例

writer.h

1
2
3
4
5
6
7
8
// writer.h

class CWriter{
 public:
  void write(int num); // 引数は int 型
  void write(char *str); // 引数は char * 型
  void write(double d); // 引数は double 型
};

writer.cpp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// writer.cpp
#include <stdio.h>
#include "writer.h"

void CWriter::write(int num){
  printf( "%d\n", num );
}

void CWriter::write(char *str){
  printf("%s\n", str);
}

void CWriter::write(double d){
  printf("%f\n", d);
}

main.cpp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// main.cpp
#include "writer.h"

int main(){
  CWriter writer;

  writer.write( 100 );
  writer.write( (char *)"wtopia" );
  writer.write( 3.1415926 );

  return 0;
}

GNUmakefile

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

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

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

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

main.o: writer.h main.cpp
writer.o: writer.h writer.cpp

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

[wtopia overload]$ ./main
100
wtopia
3.141593

コンストラクタのオーバーロード

コンストラクタもオーバーロードできる. 下記の例をみよう.

constructorol.cpp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <iostream>

class CPoint{
private:
  int m_x; // X 座標
  int m_y; // Y 座標
  
public:
  CPoint(); // 引数のないコンストラクタ
  CPoint(int x, int y); // 引数のあるコンストラクタ

  void SetXY(int x, int y); // 座標を設定する
  void GetXY(int *x, int *y); // 座標を取得する
};

// 引数のないコンストラクタ
CPoint::CPoint(){
  m_x = m_y = 0;
}

// 引数のあるコンストラクタ
CPoint::CPoint(int x, int y){
  m_x = x;
  m_y = y;
}

// 座標を設定する
void CPoint::SetXY(int x, int y){
  m_x = x;
  m_y = y;
}

// 座標を取得する
void CPoint::GetXY(int *x, int *y){
  *x = m_x;
  *y = m_y;
}

int main(){
  CPoint point1;
  CPoint point2(50, 100);
  int x, y;

  point1.GetXY( &x, &y );
  std::cout << x << " " << y << std::endl;

  point2.GetXY( &x, &y );
  std::cout << x << " " << y << std::endl;

  return 0;
}

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

[wtopia constoverload]$ g++ -Wall -O2 -o constructorol constructorol.cpp
[wtopia constoverload]$ ./constructorol
0 0
50 100

注意:

デストラクタについてはオーバーロードできない.

曖昧な引数

下記のコードがあるとして:

void Set(int x, int y); // int 型の引数
void Set(long x, long y); // long 型の引数

obj.Set(100, 200); を実行してみると, int 型の引数のある関数が呼び出される.

obj.Set( (long)100, (long)200 ); を実行してみると, long 型の引数のある関数が呼び出される.

オーバーロードと継承

オーバーロードされたコンストラクタと継承

ol_inheri.cpp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// ol_inheri.cpp
#include <iostream>

class CBase{
private:
  int m_num;

public:
  CBase(int num);
};

class CSub : public CBase{
public:
  CSub();
  CSub(int num);
};

// CBase クラスのコンストラクタ
CBase::CBase(int num){
  m_num = num;
}

// CSub クラスのコンストラクタ
CSub::CSub() : CBase(0){
  
}

// CSub クラスのコンストラクタ
CSub::CSub(int num) : CBase(num){
}


int main(){
  // CBase base; はエラーとなる
  CBase base(0);
 
  
  return 0;
}