オーバーライドしてみた・・・

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ただの屍のようだ

オーバーライドしてみた・・・

#1

投稿記事 by ただの屍のようだ » 13年前

予定より2章遅れでいまだに独習C++やってます。
章末問題やっていてふっと疑問に思ったことがあります。
プログラム:抽象クラスlistをオーバーライドしてstack(スタック),queue(キュー),sorted(整列済みリスト)を作ること。

コード:

#include<iostream>
#include "../CPP-1/myheader.h"
#include<iomanip>

using namespace std;

class list{
public:
	list *head,*tail;
	list *next;
	int num;
	list(){head=tail=next=NULL;}
	virtual void store(int) = 0;
	virtual int retrieve() = 0;
};

class stack : public list{
public:
	void store(int);
	int retrieve();
};

void stack::store(int key){
	list *p = new stack;
	if(!p) return ;
	p->num = key;
	if(head)	p->next = head;
	head = p;
}

int stack::retrieve(){
	int num;
	list *p=head;
	if(!p)	return 0;
	num=p->num;
	head = p->next;
	delete p;
	return num;
}

int main(){
	int num;
	list *p;
	stack a;		//なぜstack a(); にするとうまくいかないのかどうも説明つきません
	p = &a;
	p->store(12);	p->store(2);	p->store(322);
	while(num=p->retrieve())	cout << num << endl;
	return 0;
}
ええ、スタック作って動かしてみたらどうもコメント行の疑問が浮かびました。できれば初心者の自分にもわかるよう、丁寧な説明お願いします。

アバター
h2so5
副管理人
記事: 2212
登録日時: 15年前
住所: 東京
連絡を取る:

Re: オーバーライドしてみた・・・

#2

投稿記事 by h2so5 » 13年前

コード:

stack a();
を使うとエラーになるのは、この文をコンパイラが関数ポインタの宣言として解釈してしまうからです。

http://docs.oracle.com/cd/E19205-01/821-2504/gkgar/

ただの屍のようだ

Re: オーバーライドしてみた・・・

#3

投稿記事 by ただの屍のようだ » 13年前

たすかりました!

usao

Re: オーバーライドしてみた・・・

#4

投稿記事 by usao » 13年前

既に答えが出ていますが…
質問する際には,なにがどう「うまくいかない」のか
できれば閲覧者にもわかるよう,丁寧に説明した方がよろしいのでは?
例えば,VS2012では

コード:

class Cat
{
};

int _tmain(int argc, _TCHAR* argv[])
{
	Cat a();
	return 0;
}
に対して,
>warning C4930: 'Cat a(void)': プロトタイプされている関数が呼び出されませんでした (変数の定義が意図されていますか?)
というメッセージが出されます.
コンパイル時の問題ならば,そのようなエラーメッセージの類まで書かれると良いように思います.

ただの屍のようだ

Re: オーバーライドしてみた・・・

#5

投稿記事 by ただの屍のようだ » 13年前

こんごきをつけます。

ただの屍のようだ

Re: オーバーライドしてみた・・・

#6

投稿記事 by ただの屍のようだ » 13年前

昼はさんで問題解きました。気になるところがありました。
そう!例外処理は次の章なので今の段階では習ったものだけ使ってがんばって作りました。
熟練のみなさんならどんなコーディングするのだろうと気になりました。アドバイスなど遠慮せず申し上げてください

コード:

#include<iostream>
#include "../CPP-1/myheader.h"
#include<iomanip>

using namespace std;

class list{
public:
	list *head,*tail;
	list *next;
	int num;
	list(){head=tail=next=NULL;}
	virtual void store(int) = 0;
	virtual int retrieve() = 0;
};


class sorted : public list{
	void init();
public:
	void store(int);
	int retrieve();
};

void sorted::init(){
	head = new sorted;
	if(!head) return;
	head->num = -1;
	head->next = NULL;
}

void sorted::store(int key){
	list *p,*obj = new sorted;
	if(!obj)	return ;
	if(!head)	this->init();	//先頭に対する例外操作を取り除くため、headには空のsortedクラス一つあらかじめ代入しておく
	if(!head)	return ;		//まだ例外処理のところまで進んでないので、二度チェックでメモリの割り当て失敗を防ぐ
	for(p=head;p->next;p=p->next){
		if(!p->next) break;
		if(p->next->num >= key) break;
	}
	obj->num = key;
	obj->next = p->next;
	p->next = obj;
}

int sorted::retrieve(){
	int num;
	list *p = head->next;		//先頭の無意味なsortedクラスを飛ばす。
	if(!p) return 0;
	num = p->num;
	head->next = p->next;
	delete p;
	return num;
}

int main(){
	int num;
	list *p;
	sorted a;		//stack a();  → stack (*a)()という関数とみなされるから
	p = &a;
	p->store(12);	p->store(2);	p->store(322);
	while(num=p->retrieve())	cout << num << endl;
	return 0;
}
*->演算子使ってみました。

usao

Re: オーバーライドしてみた・・・

#7

投稿記事 by usao » 13年前

まずlistをしっかり完成させてみるべきではないでしょうか.
なんというか,継承の目的が謎というか.

リスト構造でデータを扱う機能 を再利用したいなら,
それらの処理実装はlistクラスが持っているのが自然なように思います.
(派生せずとも,stackやsortedは,単にlistをメンバに持てばよい)

listクラスの存在目的が,機能の実装を提供するのではなくて
store() と retrieve() の2つのインタフェースを規定することなのであれば,
listクラスにはメンバ変数を持たせるべきではないと思います.

ただの屍のようだ

Re: オーバーライドしてみた・・・

#8

投稿記事 by ただの屍のようだ » 13年前

教科書では、list(抽象クラス)の真価は実行時バインディングにあると書いてあります。
たとえば下のような処理が必要なときなど

コード:

list *p;
stack stk;	queue q;	sorted std;

for(int i=10;i;i--){
	if(i%3==0) p = &stk;
	else if(i%3==1) p = &q;
	else	p = &std;
	p->store(i*i);
}

usao

Re: オーバーライドしてみた・・・

#9

投稿記事 by usao » 13年前

提示されたlistクラスのコードが,その本に掲載されているものなのだとすれば,
listについて質問者様に何か言うのは筋違いですね.
(なんというか,クラスとCの構造体の狭間のような状態ですが,本の中の場所的に仕方ないのかもしれませんし)

閉鎖

“C言語何でも質問掲示板” へ戻る