Bonsoir tout le monde.
Je commence le développement d'une Lib en C++ et je désire intégrer les propriétés à cette Lib en se basant sur l'article Implementing Properties In C++. Il y aura biensure les fonctions GetXXXX et SetXXXX mais je trouve très intéressant les propriétés.
Donc, voici le code de la classe qui m'intéresse et qui j'aimerai qu'on me dise si c'est OK, si non, ce qui manque, ce qui est fait de trop, ce qui est mal fait, etc.
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
 
template <typename ObjectType, typename ValueType>
class property
{
public :
	// Type de pointeur de fonction pour Property Get
	typedef ValueType (ObjectType::*PGETTER)(void);
	// Type de pointeur de fonction pour Property Set
	typedef void (ObjectType::*PSETTER)(ValueType value);
 
private :
	// Instance de l'objet contenant la propriété à gérer
	ObjectType *m_pObject;
	// Pointeur de la fonction Property Set
	PSETTER Set;
	// Pointeur de la fonction Property Get
	PGETTER Get;
public:
	// Constructeur par défaut
	property(void)
	{
		m_pObject = NULL;
		Set = NULL;
		Get = NULL;
	}
 
	// Initialisation de la propriété
	// object : Instance de l'object contenant la propriété.
	// pGet   : Pointeur vers la fonction de récupération de la valeur de la propriété.
	// pSet   : Pointeur vers la fonction d'affectation de la valeur de la propriété.
	void Setup(ObjectType *object, PGETTER pGet, PSETTER pSet)
	{
		// TODO : Vérifier les paramètres et gérer les exceptions
		m_pObject = object;
		this->Set = pSet;
		this->Get = pGet;
	}
 
	// Vérifier l'accès en lecture
	bool CanRead(void)
	{
		return (this->GSet != NULL);
	}
 
	// Vérifier l'accès en écriture
	bool CanWrite(void)
	{
		return (this->Set != NULL);
	}
 
	// Surcharger le retour de la valeur casté au type de la propriété
	operator ValueType()
	{
		return (m_pObject->*Get)();
	}
 
	// Surcharger l'affectation
	ValueType operator =(const ValueType& value)
	{
		// TODO : Vérifier les paramètres et gérer les exceptions
		if(this->Set == NULL) throw "Propriété en lecture seule!";
		(m_pObject->*Set)(value);
		return (m_pObject->*Get)();
	}
 
	// Comparer les objets et non pas les classe property
	bool operator==(const ValueType& value)
	{
		// TODO : Vérifier les paramètres et gérer les exceptions
		return value == (m_pObject->*Get)();
	}
 
	// Surcharger l'accès au membres pour accèder au membres de l'objet de la propriété
	// et non pas l'instance de la classe property.
	ValueType *operator->()
	{
		return (m_pObject->*Get)();
	}
};
Pour plus d'informations, voici le code source du programme contenant la classe en question, des classes pour le teste et une main pour tester.
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
 
#include <stdio.h>
 
////////////////////////////////////////////////////////////////////////////////
template <typename ObjectType, typename ValueType>
class property
{
public :
	// Type de pointeur de fonction pour Property Get
	typedef ValueType (ObjectType::*PGETTER)(void);
	// Type de pointeur de fonction pour Property Set
	typedef void (ObjectType::*PSETTER)(ValueType value);
 
private :
	// Instance de l'objet contenant la propriété à gérer
	ObjectType *m_pObject;
	// Pointeur de la fonction Property Set
	PSETTER Set;
	// Pointeur de la fonction Property Get
	PGETTER Get;
public:
	// Constructeur par défaut
	property(void)
	{
		m_pObject = NULL;
		Set = NULL;
		Get = NULL;
	}
 
	// Initialisation de la propriété
	// object : Instance de l'object contenant la propriété.
	// pGet   : Pointeur vers la fonction de récupération de la valeur de la propriété.
	// pSet   : Pointeur vers la fonction d'affectation de la valeur de la propriété.
	void Setup(ObjectType *object, PGETTER pGet, PSETTER pSet)
	{
		// TODO : Vérifier les paramètres et gérer les exceptions
		m_pObject = object;
		this->Set = pSet;
		this->Get = pGet;
	}
 
	// Vérifier l'accès en lecture
	bool CanRead(void)
	{
		return (this->GSet != NULL);
	}
 
	// Vérifier l'accès en écriture
	bool CanWrite(void)
	{
		return (this->Set != NULL);
	}
 
	// Surcharger le retour de la valeur casté au type de la propriété
	operator ValueType()
	{
		return (m_pObject->*Get)();
	}
 
	// Surcharger l'affectation
	ValueType operator =(const ValueType& value)
	{
		// TODO : Vérifier les paramètres et gérer les exceptions
		if(this->Set == NULL) throw "Propriété en lecture seule!";
		(m_pObject->*Set)(value);
		return (m_pObject->*Get)();
	}
 
	// Comparer les objets et non pas les classe property
	bool operator==(const ValueType& value)
	{
		// TODO : Vérifier les paramètres et gérer les exceptions
		return value == (m_pObject->*Get)();
	}
 
	// Surcharger l'accès au membres pour accèder au membres de l'objet de la propriété
	// et non pas l'instance de la classe property.
	ValueType *operator->()
	{
		return (m_pObject->*Get)();
	}
};
////////////////////////////////////////////////////////////////////////////////
 
// Juste pour tester Intellisense pour l'affichage de la liste des membres d'une classe
// avec l'opérateur surchargé "->" de la classe property
class Redirection
{
public :
	int i;
	Redirection()
	{
		i = (int)this;
	}
};
////////////////////////////////////////////////////////////////////////////////
 
// Implémentation des propriétés dans une classe
class Test
{
public :
	// Constructeur par défaut
	Test()
	{
		// Initialiser la valeur de la propriété Count
		m_Count = 0;
		// Préparer les paramètres de fonctionnement de la propriété Count en lecture/écriture
		Count.Setup(this, &Test::GetCount, &Test::SetCount);
		// Préparer les paramètres de fonctionnement de la propriété Redirectional en lecture seule
		Redirectional.Setup(this, &Test::GetRedirection, NULL);
	}
 
	Test(int init)
	{
		m_Count = init;
		// Préparer les paramètres de fonctionnement de la propriété Count en lecture/écriture
		Count.Setup(this, &Test::GetCount, &Test::SetCount);
		// Préparer les paramètres de fonctionnement de la propriété Redirectional en lecture seule
		Redirectional.Setup(this, &Test::GetRedirection, NULL);
	}
 
	// Property setter de la propriété Count
	void SetCount(int value)
	{
		printf("SetCount called\n");
		m_Count = value;
	}
 
	// Property getter de la propriété Count
	int GetCount(void)
	{
		printf("GetCount called\n");
		return m_Count;
	}
 
	// Property getter de la propriété Redirectional
	Redirection GetRedirection(void)
	{
		return this->m_redir;
	}
 
public :
	// Déclaration de la propriété Count
	property<Test, int> Count;
	// Déclaration de la propriété Redirectional
	property<Test, Redirection> Redirectional;
 
private :
	// Variable contenant la valeur de la propriété Count
	int m_Count;
	// Object de la propriété Redirectional
	Redirection m_redir;
};
////////////////////////////////////////////////////////////////////////////////
 
// Programme principal
// Quelques testes...
int main(void)
{
	try {
		Test test;
		test.Count = 11;
		int i = test.Count;
		Test *pTest = new Test();
		pTest->Count = 2;
		printf("%d + %d = %d\n", (int)pTest->Count, (int)test.Count, pTest->Count + test.Count);
		pTest->Count = test.Count;
		printf("%d + %d = %d\n", (int)pTest->Count, (int)test.Count, pTest->Count + test.Count);
		Redirection redir;
		pTest->Redirectional = redir; // Affectation d'une propriété en lecture seule
		delete pTest;
	} catch (char *message) {
		printf("Exception levée!\n\t%s\n", message);
	} catch (...) {
		printf("Exception non gérée levée!..");
	}
	while(true);
}
Je suis ouvert à tout commentaire, critère, conseil ou autre.
Merci.