アフィリエイト広告を利用しています

広告

posted by fanblog

2018年02月02日

《その272》 抽象クラステンプレート


 抽象クラステンプレート

 下記のプログラムで、クラステンプレート Stack<> のメンバ関数は、すべて純粋仮想関数になっています。このような、クラステンプレートは抽象クラステンプレートと呼ばれ、具体性のない概念のみを定義しているため、この抽象クラステンプレートから直接 クラスオブジェクトを生成することはできません。

 抽象クラステンプレートに具体性を持たせるのは、派生クラスの役目です。下記のプログラムでは、
抽象クラステンプレート Stack<> から public派生した ArrayStack<> が、「スタックを配列で実現する」という具体的なクラステンプレートになっています。

 以下のプログラムでは、クラステンプレート ArrayStack<> を、ArrayStack<int> として利用し、整数値用のスタックを配列で実現しています。

#include <iostream>

// ------------------------------------

// 抽象クラステンプレート Stack<>

template <class Type> class Stack {
public:
class Overflow { }; // Overflow例外
class Empty { }; // Empty例外

// 純粋仮想デストラクタ
virtual ~Stack() = 0;

// 純粋仮想関数 push
virtual void push(const Type&) = 0;

// 純粋仮想関数 pop
virtual Type pop() = 0;
};

template <class Type>
Stack<Type>::~Stack() { }

// ------------------------------------

// クラステンプレート ArrayStack<>
template <class Type> class ArrayStack
: public Stack<Type> {
// データ収納用配列の要素数
static const int size = 6;

int ptr; // スタックポインタ
Type stk[size]; // スタックの本体

public:
ArrayStack() : ptr(0) { }
~ArrayStack() { }

void push(const Type& x) {
if (ptr >= size)
throw Stack<Type>::Overflow();
stk[ptr++] = x;
}

Type pop() {
if (ptr <= 0)
throw Stack<Type>::Empty();
return stk[--ptr];
}
};

// ------------------------------------

int main() {
ArrayStack<int> a;
try {
for (int i = 0; i < 6; i++)
a.push(100 + i);
}
catch (const Stack<int>::Overflow&) {
std::cout << "Overflow!\n";
}

try {
for (int i = 0; i < 6; i++)
std::cout << a.pop() << ' ';
std::cout << '\n';
}
catch (const Stack<int>::Empty&) {
std::cout << "Empty!\n";
}

Stack<int>* p1 = &a;
std::cout << "ポインタの型 : ";
std::cout << typeid(p1).name() << '\n';
std::cout << "オブジェクトの動的な型 : ";
std::cout << typeid(*p1).name() << '\n';

std::cout << "------------\n";

Stack<int>* p2 = new ArrayStack<int>();
try {
for (int i = 0; i < 6; i++)
p2->push(100 + i);
}
catch (const Stack<int>::Overflow&) {
std::cout << "Overflow!\n";
}

try {
for (int i = 0; i < 6; i++)
std::cout << p2->pop() << ' ';
std::cout << '\n';
}
catch (const Stack<int>::Empty&) {
std::cout << "Empty!\n";
}

std::cout << "ポインタの型 : ";
std::cout << typeid(p2).name() << '\n';
std::cout << "オブジェクトの動的な型 : ";
std::cout << typeid(*p2).name() << '\n';

delete p2;
}

f09_0072.png



この記事へのコメント
コメントを書く

お名前:

メールアドレス:


ホームページアドレス:

コメント:

※ブログオーナーが承認したコメントのみ表示されます。

この記事へのトラックバックURL
https://fanblogs.jp/tb/7269427
※ブログオーナーが承認したトラックバックのみ表示されます。

この記事へのトラックバック

 たまに、クリック お願いします m(_ _)m

 AA にほんブログ村 IT技術ブログ C/C++へ

こうすけ:メール kousuke_cpp@outlook.jp

【1】★★C++ 記事目次★★ ← 利用可能です。
・新版明解C++入門編 / 新版明解C++中級編
・その他 C++ 関連記事

【2】★★こうすけ@C#★★
・C# の初歩的な記事


検索
<< 2018年08月 >>
      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  
プロフィール
こうすけさんの画像
こうすけ

 たまに、クリック お願いします m(_ _)m

 AA にほんブログ村 IT技術ブログ C/C++へ

こうすけ:メール kousuke_cpp@outlook.jp

【1】★★C++ 記事目次★★ ← 利用可能です。
・新版明解C++入門編 / 新版明解C++中級編
・その他 C++ 関連記事

【2】★★こうすけ@C#★★
・C# の初歩的な記事


×

この広告は30日以上新しい記事の更新がないブログに表示されております。