2018年01月29日
《その263》 インクルードモデル & p.349演習9-7
インクルードモデル
規模の大きいクラステンプレートで、単一のヘッダでの管理が難しい場合、その対処法の1つに、インクルードモデルと呼ばれる手法があります。
この手法では、2つのヘッダを使います。一方のヘッダで、クラスの定義(メンバ関数は宣言のみにしておく)を行い、もう一方のヘッダでは、実装作業的なメンバ関数の定義等を行います。
インクルードモデルの具体的な手法については、今回の 演習9-7 と次回の 演習9-8 が参考になると思います。
新版明解C++中級編 p.349 演習9-7
下記のクラステンプレート Twin<> をインクルードモデルで実現したプログラムを作成せよ。
// Twin.h
#ifndef ___Class_Twin
#define ___Class_Twin
#include <utility>
#include <algorithm>
template <class Type> class Twin {
Type v1;
Type v2;
public:
Twin(const Type& f = Type(), const Type& s = Type())
: v1(f), v2(s) { }
Twin(const Twin<Type>& t)
: v1(t.first()), v2(t.second()) { }
Type first() const { return v1; } // v1 のゲッタ
Type& first() { return v1; } // v1 のゲッタ かつ セッタ
Type second() const { return v2; } // v2 のゲッタ
Type& second() { return v2; } // v2 のゲッタ かつ セッタ
void set(const Type& f, const Type& s) {
v1 = f; v2 = s;
}
Type min() const { return v1 < v2 ? v1 : v2; }
bool ascending() const { return v1 < v2; }
void sort() { if (!(v1 < v2)) std::swap(v1, v2); }
};
template <class Type> inline std::ostream& operator<<(
std::ostream& os, const Twin<Type>& t
) {
return os << "[" << t.first()
<< ", " << t.second() << "]";
}
#endif
// TwinTest.cpp
#include <string>
#include <iostream>
#include "Twin.h"
using namespace std;
int main()
{
const Twin<int> t1(15, 37);
cout << "t1 = " << t1 << '\n';
Twin<string> t2("ABC", "XYZ");
cout << "t2 = " << t2 << "\n\n";
cout << "t2の値を変更します。\n";
cout << "新しい第一値:";
cin >> t2.first();
cout << "新しい第二値:";
cin >> t2.second();
if (!t2.ascending()) {
cout << "第一値<第二値 が成立"
"しないのでソートします。\n";
t2.sort();
cout << "t2は" << t2
<< "に変更されました。\n";
}
}
問題で与えられた Twin.h を、Twin.h と TwinImplementation.h の2つに分けて、
インクルードモデルを実現しました。
// 解答
// Twin.h
#ifndef ___Class_Twin
#define ___Class_Twin
#include <utility>
#include <algorithm>
template <class Type> class Twin {
Type v1;
Type v2;
public:
Twin(
const Type& f = Type(),
const Type& s = Type()
);
Twin(const Twin<Type>& t);
Type first() const;
Type& first();
Type second() const;
Type& second();
void set(const Type& f, const Type& s);
Type min() const;
bool ascending() const;
void sort();
};
// ソース部をインクルード
#include "TwinImplementation.h"
#endif
// TwinImplementation.h
#ifndef ___Class_TwinImplementation
#define ___Class_TwinImplementation
template<class Type>
Twin<Type>::Twin(
const Type& f,
const Type& s
) : v1(f), v2(s) { }
template<class Type>
Twin<Type>::Twin(const Twin<Type>& t)
: v1(t.first()), v2(t.second()) { }
template<class Type>
Type Twin<Type>::first() const { return v1; }
template<class Type>
Type& Twin<Type>::first() { return v1; }
template<class Type>
Type Twin<Type>::second() const { return v2; }
template<class Type>
Type& Twin<Type>::second() { return v2; }
template<class Type>
void Twin<Type>::set(const Type& f, const Type& s) {
v1 = f; v2 = s;
}
template<class Type>
Type Twin<Type>::min() const { return v1 < v2 ? v1 : v2; }
template<class Type>
bool Twin<Type>::ascending() const { return v1 < v2; }
template<class Type>
void Twin<Type>::sort() { if (!(v1 < v2)) std::swap(v1, v2); }
template <class Type> inline std::ostream& operator<<(
std::ostream& os, const Twin<Type>& t
) {
return os << "[" << t.first()
<< ", " << t.second() << "]";
}
#endif
// TwinTest.cpp
#include <string>
#include <iostream>
#include "Twin.h"
using namespace std;
int main()
{
const Twin<int> t1(15, 37);
cout << "t1 = " << t1 << '\n';
Twin<string> t2("ABC", "XYZ");
cout << "t2 = " << t2 << "\n\n";
cout << "t2の値を変更します。\n";
cout << "新しい第一値:";
cin >> t2.first();
cout << "新しい第二値:";
cin >> t2.second();
if (!t2.ascending()) {
cout << "第一値<第二値 が成立"
"しないのでソートします。\n";
t2.sort();
cout << "t2は" << t2
<< "に変更されました。\n";
}
}
この記事へのコメント
コメントを書く
この記事へのトラックバックURL
https://fanblogs.jp/tb/7253373
※ブログオーナーが承認したトラックバックのみ表示されます。
この記事へのトラックバック