/* ex_5_4.c++ */
#include <iostream>
#include <string>
#include <queue>
using namespace std;

/* *** identifiable *** */
class identifiable {
	string article;
protected:
	void set_genre(const int&);
	string get_article() const { return article; };
public:
        virtual string get_identification() const = 0;
};

void identifiable::set_genre(const int& genre) {
	switch (genre) {
  		case 1:
			article = "Un ";
			break;
  		case 2:
			article = "Une ";
			break;
		default:
			article = "";
	}
}

/* *** utile *** */
class utile {
public:
        virtual string get_fonction() const = 0;
};

/* *** objet *** */
class objet : public identifiable, public utile {
	string nom, fonction;

public:
	objet(string n, string f, int genre);
	string get_identification () const { return (get_article() + nom); };
	string get_fonction () const { return fonction; };
};

objet::objet(string n, string f, int genre=0) :
	nom(n),
	fonction(f) {
	set_genre(genre);
}

/* *** truc *** */
class truc : public identifiable {
public:
	string get_identification () const { return "un truc."; };
};

/* *** machin *** */
class machin : public identifiable {
public:
	string get_identification () const { return "un machin."; };
};

/* *** main *** */
int main (void) {
	queue<identifiable*> la_queue;
	int nb;

	cout << "Combien de choses ?" << endl << "> ";
	cin >> nb;
	while(nb--) la_queue.push(new objet("chose", "utile", 2));
	cout << "Combien de trucs ?" << endl << "> ";
	cin >> nb;
	while(nb--) la_queue.push(new truc());
	cout << "Combien de machins ?" << endl << "> ";
	cin >> nb;
	while(nb--) la_queue.push(new machin());

	while (!la_queue.empty()) {
		identifiable* ptr = la_queue.front();
		cout << ptr->get_identification() << endl;
		delete ptr;
		la_queue.pop();
	}
	return 0;
}
