読者です 読者をやめる 読者になる 読者になる

@uents blog

Code wins arguments.

ロベールのC++入門講座でC++を初歩から入門する(7日目)

C++

13章 もっと深く(続き)

「13-14 関数ポインタ天国」から。

関数ポインタはCで散々やってるので分かっているつもり。メンバ関数ポインタの文法は普通の関数ポインタとちょっと違うので写経。

/**
 * @file MemFuncPointer.cpp
 */
#include <iostream>
using namespace std;

class Calculator {
	typedef int (Calculator::*FuncPtr)(); // メンバ関数ポインタの型定義
	struct Operator {
		const char* name;
		FuncPtr func;
	};
	static const Operator FP_OPERATORS[];

public:
	void Run();

private:
	int m_a, m_b;
	int Add() { return m_a + m_b; }
	int Sub() { return m_a - m_b; }
	int Mul() { return m_a * m_b; }
	int Div() { return m_a / m_b; }

	bool Input();
	void Calculate();
};

const Calculator::Operator Calculator::FP_OPERATORS[] = {
	// メンバ関数のポインタを代入していく
	{"Add", &Calculator::Add},
	{"Sub", &Calculator::Sub},
	{"Mul", &Calculator::Mul},
	{"Div", &Calculator::Div},
};

void Calculator::Run() {
	while(Input()) {
		Calculate();
	}
}

bool Calculator::Input() {
	cout << "input a pair of values > " << flush;
	m_b = 0;
	cin >> m_a >> m_b;
	return m_b != 0;
}

void Calculator::Calculate() {
	for (int i = 0; i < sizeof(FP_OPERATORS)/sizeof(*FP_OPERATORS); i++) {
		const Calculator::Operator* op = &(this->FP_OPERATORS[i]);
		int result = (this->*(op->func))(); // メンバ関数の呼び出し。this->*は省略不可
		cout << op->name << " : " << result << endl;
	}
}

int main() {
	Calculator calc;
	calc.Run();
	return 0;
}

実行結果。

% ./MemFuncPointer
./MemFuncPointer
input a pair of values > 1 2 
1 2 
Add : 3
Sub : -1
Mul : 2
Div : 0
input a pair of values > 0 0
%

メンバ変数ポインタの場合も上記と同様->*(または.*)が必要。

14章 もっともっと深く

C++特有というより、C/C++共通の話題が多い

  • ショートサーキット
  • voidへのポインタ。Cでは使いまくり。C++の場合は明示的なキャストが必要
  • #ifディレクティブ
  • 組み込みマクロ。__FUNCTION__は標準マクロじゃないんだ(gcc拡張?C++にないだけ?)
  • 可変個引数
  • コマンドライン引数。各IDEでの指定方法もまとめてあって親切
  • アライメント。#pragma packは知らなかった
  • プリコンパイル済みヘッダファイル。へーこんなのあるんだ

動作仕様のCOLUMNがおもしろい

  • 処理系定義の動作 (implementaiton-defined behavior)
  • 未定義の動作 (undefined behavior)
  • 未規定の動作 (unspecified behavior)

こういう用語を正しく使い分けられることもプログラマにとっては大事。


次回は「15章 データ構造」から。あと少し!