Bonjour,

je poste sur ce forum pour la première fois afin d'obtenir une réponse à mon problème. Je travaille actuellement sur une grammaire abstraite permettant de reconnaitre (par la voix) un langage. Je résume la situation:
- Une grammaire possède plusieurs règles.
- Une règle possède plusieurs items.
- Un item peut-être (via héritage): un texte ou alors un noeud.
- Un noeud peut-être (via héritage): une liste, une phrase ou une éventualité.
- Un noeud possède la propriété de pouvoir posséder d'autres items.

Ce problème semble donc plutôt bien disposer à être résolu via un pattern Composite. Je désire, à partir d'un Item, pouvoir remonter à sa règle directe ou son noeud direct. Je possède donc deux méthodes renvoyant des pointeurs sur la chose.

L'idée est que l'utilisateur puisse créer une grammaire, ses règles, ses items, puis plus tard, récupérer un item et ajouter directement un item frère dans une liste par exemple. (En récupérant donc la règle mère OU le noeud père et en invoquant la méthode d'ajout d'item, le tout sans besoin de cast).

Voici la classe Item:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
 
class Item
{
public:
	// returns name of item.
	const std::wstring &getName() const;
	// returns id of item.
	unsigned long getID() const;
	// returns mother rule of item (never NULL).
	Rule *getRuleMother() const;
	// returns father node of item (may be NULL).
	Node *getnodeFather() const;
	// returns true if item is a direct rule child
	bool isRuleChild() const;
 
protected:
	// Constructors of an item. 
	// CONS_1 ruleMother: pointer to the mother rule if item is direct child of a rule.
	// CONS_2 nodeFather: pointer to the father node if item is direct child of a node.
	Item(const std::wstring &name, unsigned long id, Rule *ruleMother);
	Item(const std::wstring &name, unsigned long id, Node *nodeFather);
	// Only an itemCreator can delete an Item.
	friend void ItemCreator::freeItem(Item *item);
	virtual ~Item() {}; 
private:
	Node *nodeFather;
	Rule *ruleMother;
};
Et la classe Node:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
 
class Node: public Item
{
public:
	unsigned long getNumberOfItems() const;
	unsigned long getItems(std::vector<Item*> &result) const;
	Item *getItem(unsigned long itemID) const;
 
	// Item creation. Returns a pointer on created Item (never NULL).
	// Constructors are available with and without name (empty name).
	// text: text to recognize.
	Text *createText(const std::wstring &name, const std::wstring &text);
	Text *createText(const std::wstring &text);
	Phrase *createPhrase(const std::wstring &name);
	Phrase *createPhrase();
	List *createList(const std::wstring &name);
	List *createList();
	Option *createOption(const std::wstring &name);
	Option *createOption();
	// deletes a direct item of a node. Returns true if operation is a success.
	bool deleteItem(unsigned long itemID);
protected:
	Node(const std::wstring &name, unsigned long id, Rule *ruleMother, ItemRegistrar &registrar);
	Node(const std::wstring &name, unsigned long id, Node *nodeFather, ItemRegistrar &registrar);
	virtual ~Node(); // delete all items
private:
	Node(const Node &n);
private:
	ItemContainer items;
	ItemCreator itemCreator;
};
Plusieurs remarques sur le code:
- L'utilisation de pointeurs résulte du fait que je désire que le module que je développe soit cohérent et uniforme (je ne veux pas d'un get référence et d'un autre get pointeur).
- La non utilisation de références provient du fait que je ne désire pas utiliser d'exceptions et que dans le cas d'une recherche, il est impossible de retourner une réference NULL.

Pour l'instant, comme vous le remarquez, je possède un pointeur sur une classe fille dans la classe mère. Ceci parait étrange, et pourtant, ca me parait la solution la moins "pénible". De plus, ma classe Rule ne peut pas hériter d'Item, je perds alors l'application du pattern composite...
Le pattern Composite peut être vu de deux façons:
- La classe mère déclare les fonctions d'ajout et de récupération mais lance une exception par défaut. La classe feuille ne surcharge pas la méthode, mais la classe fille composite, si.
- la classe mère ne possède pas les fonctions d'ajout et de récupération et il est nécessaire de downcaster le pointeur en classe fille.

Je cherche une solution sans downcast, et pas crade de préférence .

Une autre question est: Dans le cas où cette architecture est considérée comme Fixe (i.e., seul un Node peut posséder d'autres Items), est-ce un mal ABSOLU de parler d'une classe fille dans la classe mère ? (sachant que ca ne brise pas l'extension du code car il s'agira simplement d'hériter de la classe Fille si on veut ajouter un nouvel élement).

Merci d'avance pour vos réponses .

Pierrick