Witam,
Mam problem z zadaniem z książki S. Prata. Zadanie dotyczy utworzenia szablonu QueueTP i przetestowania jego działania tworząc kolejkę wskaźników na klasę Worker. Kolejkę szablonową utworzyłem na podstawie zwykłej kolejki, więc nie wiem czy jest na 100% dobra. Z kolei klasa Worker jest prawidłowo zadeklarowana i zaimplementowana, bo przepisałem z książki. Przy kompilacji programu wyświetla się jeden warning o treści: użycie potencjalnie niezainicjowanej, lokalnej zmiennej wskaźnikowej pt.
W takim razie przypuszczam, że błąd jest w programie głównym, ale nie umiem go znaleźć. Poniżej wrzucam kod programu głównego:
#include "stdafx.h"
#include "QueueTP.h"
#include <cstring>
#include <new>
#include "workermi.h"
int main()
{
using std::cin;
using std::cout;
using std::endl;
using std::strchr;
const int BUFFOR = 512;
char * bufor = new char[BUFFOR];
cout << "Podaj maksymalna dlugosc kolejki: ";
int qs;
char ch;
cin >> qs;
QueueTP<Worker *> line(qs);
Worker * pt;
cout << "Nacisnij D, aby wprowadzic strukture, \n"
<< "P, aby przetworzyc strukture, lub K, aby zakonczyc.\n";
cin.get();
while (cin >> ch && toupper(ch) != 'K')
{
while (cin.get() != '\n')
continue;
if (!isalpha(ch))
{
cout << '\a';
continue;
}
switch (ch)
{
case 'D':
case 'd':
if (line.isfull())
cout << "Kolejka pelna!\n";
char choice;
cout << "Podaj kategorie pracownika:\n"
<< "k: kelner p: piosenkarz "
<< "s: spiewajacy kelner w: wyjscie\n";
cin >> choice;
while (strchr("kpsw", choice) == NULL)
{
cout << "Wpisz k, p, s lub w: ";
cin >> choice;
}
if (choice == 'w')
break;
switch(choice)
{
case 'k': pt = new(bufor) Waiter;
break;
case 'p': pt = new(bufor) Singer;
break;
case 's': pt = new(bufor) SingingWaiter;
break;
}
cin.get();
pt->Set();
line.enqueue(pt);
break;
case 'P':
case 'p':
if (line.isempty())
cout << "Kolejka pusta\n";
else
{
cout << "Obiekt sciagniety z poczatku kolejki:\n";
line.dequeue(pt);
pt->Show();
delete pt;
}
break;
default:
cout << "Wybrales zla opcje!\n";
break;
}
cout << "\nNacisnij D, aby wprowadzic strukture, \n"
<< "P, aby przetworzyc strukture, lub K, aby zakonczyc.\n";
}
delete [] bufor;
return 0;
}
Plik nagłówkowy z abstrakcyjną klasą Worker i jej pochodnymi klasami, oraz implementacje w osobnym pliku:
#pragma once
#ifndef WORKERMI_H_
#define WORKERMI_H_
#include <iostream>
#include <string>
class Worker
{
private:
std::string fullname;
long id;
protected:
virtual void Data() const;
virtual void Get();
public:
Worker()
: fullname("brak"), id(0L) {}
Worker(const std::string & s, long n)
: fullname(s), id(n) {}
virtual ~Worker() = 0; //funkcja czysto wirtualna
virtual void Set() = 0;
virtual void Show() const = 0;
};
class Waiter : virtual public Worker
{
private:
int panache;
protected:
virtual void Data() const;
virtual void Get();
public:
Waiter()
: Worker(), panache(0) {}
Waiter(const std::string & s, long n, int p = 0)
: Worker(s, n), panache(p) {}
Waiter(const Worker & wk, int p = 0)
: Worker(wk), panache(p) {}
void Set();
void Show() const;
};
class Singer : virtual public Worker
{
protected:
enum {inna, alt, kontralt, sopran, bas, baryton, tenor};
enum {Vtypes = 7};
virtual void Data() const;
virtual void Get();
private:
static const char *pv[Vtypes]; //odpowiednik skali głosu w postaci ciągu znaków
int voice;
public:
Singer()
: Worker(), voice(inna) {}
Singer(const std::string & s, long n, int v = inna)
: Worker(s, n), voice(v) {}
Singer(const Worker & wk, int v = inna)
: Worker(wk), voice(v) {}
void Set();
void Show() const;
};
class SingingWaiter : public Singer, public Waiter
{
protected:
virtual void Data() const;
virtual void Get();
public:
SingingWaiter() {}
SingingWaiter(const std::string & s, long n, int p = 0, int v = inna)
: Worker(s, n), Waiter(s, n, p), Singer(s, n, v) {}
SingingWaiter(const Worker & wk, int p = 0, int v = inna)
: Worker(wk), Waiter(wk, p), Singer(wk, v) {}
SingingWaiter(const Worker & wt, int v = inna)
: Worker(wt), Waiter(wt), Singer(wt, v) {}
SingingWaiter(const Singer & wt, int p = 0)
: Worker(wt), Waiter(wt, p), Singer(wt) {}
void Set();
void Show() const;
};
#endif
#include "stdafx.h"
#include "workermi.h"
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
//metody klasy Worker
Worker::~Worker() {}
//metody chronione
void Worker::Data() const
{
cout << "Imie i nazwisko: " << fullname << endl;
cout << "numer identyfikacyjny: " << id << endl;
}
void Worker::Get()
{
getline(cin, fullname);
cout << "Podaj numer identyfikacyjny: ";
cin >> id;
while (cin.get() != '\n')
continue;
}
//metody klasy Waiter
void Waiter::Set()
{
cout << "Podaj imie i nazwisko kelnera: ";
Worker::Get();
Get();
}
void Waiter::Show() const
{
cout << "Kategoria: kelner\n";
Worker::Data();
Data();
}
//metody chronione
void Waiter::Data() const
{
cout << "Elegancja: " << panache << endl;
}
void Waiter::Get()
{
cout << "Podaj poziom elegancji kelner: ";
cin >> panache;
while (cin.get() != '\n')
continue;
}
//metody klasy Singer
const char * Singer::pv[Singer::Vtypes] = { "inna", "alt", "kontralt", "sopran", "bas", "baryton", "tenor" };
void Singer::Set()
{
cout << "Podaj imie i nazwisko piosenkarza: ";
Worker::Get();
Get();
}
void Singer::Show() const
{
cout << "Kategoria: piosenkarz\n";
Worker::Data();
Data();
}
//metody chronione
void Singer::Data() const
{
cout << "Skala glosu: " << pv[voice] << endl;
}
void Singer::Get()
{
cout << "Podaj numer dla skali glosu piosenkarza:\n";
int i;
for (i = 0; i < Vtypes; i++)
{
cout << i << ": " << pv[i] << " ";
if (i % 4 == 3)
cout << endl;
}
if (i % 4 != 0)
cout << "\n";
cin >> voice;
while (cin.get() != '\n')
continue;
}
//metody klasy SingingWaiter
void SingingWaiter::Get()
{
Waiter::Get();
Singer::Get();
}
void SingingWaiter::Data() const
{
Singer::Data();
Waiter::Data();
}
void SingingWaiter::Set()
{
cout << "Podaj imie i nazwisko spiewajacego kelnera: ";
Worker::Get();
Get();
}
void SingingWaiter::Show() const
{
cout << "Kategoria: spiewajacy kelner\n";
Worker::Data();
Data();
}
oraz klasę szablonową kolejki QueueTP z implementacją w osobnym pliku:
#ifndef QUEUETP_H_
#define QUEUETP_H_
#include <string>
#include <iostream>
template <typename Item>
class QueueTP
{
protected:
//definicje zasiegu klasy
//Node to definicja zagnieżdżona klasy, lokalna względem tej klasy
struct Node { Item item; struct Node * next; };
enum { Q_SIZE = 10 };
//prywatne składowe klasy
Node * front; //wskaźnik czoła kolejki
Node * rear; //wskaźnik ogona kolejki
int items; //bieżąca liczba elementów
const int qsize; //maksymalna liczba elementów kolejki
//definicje blokujące publiczny dostęp do operacji kopiowania
QueueTP(const QueueTP & q) : qsize(0) {}
QueueTP & operator=(const QueueTP & q) { return *this; }
public:
QueueTP(int qs); //tworzy kolejkę o pojemności qs
~QueueTP();
bool isempty() const;
bool isfull() const;
int queuecount() const;
bool enqueue(const Item &item); //dodaje element na koniec kolejki
bool dequeue(Item & item); //wyciąga element z czoła kolejki
bool operator>(const QueueTP & l)
{
if (this->items > l.items)
return true;
return false;
}
};
#endif
#include "stdafx.h"
#include "QueueTP.h"
#include <cstdlib>
//metody klasy Queue
template <typename Item>
QueueTP<Item>::QueueTP(int qs) : qsize(qs)
{
front = rear = nullptr;
items = 0;
}
template <typename Item>
QueueTP<Item>::~QueueTP()
{
Node * temp;
while (front != NULL) //do wyczerpania kolejki
{
temp = front; //zachowanie adresu elementu bieżącego
front = front->next; //przesunięcie wskaźnika do elementu następnego
delete temp; //zwolnienie elementu spod zapamiętanego adresu
}
}
template <typename Item>
bool QueueTP<Item>::isempty() const
{
return items == 0;
}
template <typename Item>
bool QueueTP<Item>::isfull() const
{
return items == qsize;
}
template <typename Item>
int QueueTP<Item>::queuecount() const
{
return items;
}
//dodaje element do kolejki
template <typename Item>
bool QueueTP<Item>::enqueue(const Item &item)
{
if (isfull())
return false;
Node * add = new Node; //utworzenie węzła
//w przypadku niepowodzenia przydziału new zrzudzi wyjątek na std::bad_alloc
add->item = item; //ustawienie wskaźników węzłów
add->next = nullptr;
items++;
if (front == NULL) //jeśli kolejka pusta
front = add; //umieść element na czele listy
else
rear->next = add; //w przeciwnym wypadku dołącz do końca
rear = add; //rear wskazuje teraz nowy węzeł
return true;
}
//kopiuje element czołowy kolejki do argumentu wywołania i usuwa go z kolejki
template <typename Item>
bool QueueTP<Item>::dequeue(Item & item)
{
if (front == NULL)
return false;
item = front->item; //skopiowanie do item pierwszego elementu
items--;
Node * temp = front; //zachowanie położenia pierwszego elementu
front = front->next; //przestawienie wskaźnika front na następny element
delete temp; //usunięcie dotychczasowego pierwszego elementu
if (items == 0)
rear = NULL;
return true;
}
Proszę o pomoc.