/src/wxwidgets/include/wx/object.h
Line | Count | Source |
1 | | ///////////////////////////////////////////////////////////////////////////// |
2 | | // Name: wx/object.h |
3 | | // Purpose: wxObject class, plus run-time type information macros |
4 | | // Author: Julian Smart |
5 | | // Modified by: Ron Lee |
6 | | // Created: 01/02/97 |
7 | | // Copyright: (c) 1997 Julian Smart |
8 | | // (c) 2001 Ron Lee <ron@debian.org> |
9 | | // Licence: wxWindows licence |
10 | | ///////////////////////////////////////////////////////////////////////////// |
11 | | |
12 | | #ifndef _WX_OBJECTH__ |
13 | | #define _WX_OBJECTH__ |
14 | | |
15 | | // ---------------------------------------------------------------------------- |
16 | | // headers |
17 | | // ---------------------------------------------------------------------------- |
18 | | |
19 | | // This really shouldn't be done here, but keep including this header for |
20 | | // compatibility as it used to be included from here in the previous versions |
21 | | // of wx and a lot of code would be broken by removing it. |
22 | | #ifndef WXBUILDING |
23 | | #include "wx/string.h" |
24 | | #endif |
25 | | |
26 | | // based on the value of wxUSE_EXTENDED_RTTI symbol, |
27 | | // only one of the RTTI system will be compiled: |
28 | | // - the "old" one (defined by rtti.h) or |
29 | | // - the "new" one (defined by xti.h) |
30 | | #include "wx/xti.h" |
31 | | #include "wx/rtti.h" |
32 | | |
33 | | #define wxIMPLEMENT_CLASS(name, basename) \ |
34 | | wxIMPLEMENT_ABSTRACT_CLASS(name, basename) |
35 | | |
36 | | #define wxIMPLEMENT_CLASS2(name, basename1, basename2) \ |
37 | | wxIMPLEMENT_ABSTRACT_CLASS2(name, basename1, basename2) |
38 | | |
39 | | // ----------------------------------- |
40 | | // for pluggable classes |
41 | | // ----------------------------------- |
42 | | |
43 | | // NOTE: this should probably be the very first statement |
44 | | // in the class declaration so wxPluginSentinel is |
45 | | // the first member initialised and the last destroyed. |
46 | | |
47 | | // _DECLARE_DL_SENTINEL(name) wxPluginSentinel m_pluginsentinel; |
48 | | |
49 | | #if wxUSE_NESTED_CLASSES |
50 | | |
51 | | #define _DECLARE_DL_SENTINEL(name, exportdecl) \ |
52 | | class exportdecl name##PluginSentinel { \ |
53 | | private: \ |
54 | | static const wxString sm_className; \ |
55 | | public: \ |
56 | | name##PluginSentinel(); \ |
57 | | ~name##PluginSentinel(); \ |
58 | | }; \ |
59 | | name##PluginSentinel m_pluginsentinel |
60 | | |
61 | | #define _IMPLEMENT_DL_SENTINEL(name) \ |
62 | | const wxString name::name##PluginSentinel::sm_className(#name); \ |
63 | | name::name##PluginSentinel::name##PluginSentinel() { \ |
64 | | wxPluginLibrary *e = (wxPluginLibrary*) wxPluginLibrary::ms_classes.Get(#name); \ |
65 | | if( e != 0 ) { e->RefObj(); } \ |
66 | | } \ |
67 | | name::name##PluginSentinel::~name##PluginSentinel() { \ |
68 | | wxPluginLibrary *e = (wxPluginLibrary*) wxPluginLibrary::ms_classes.Get(#name); \ |
69 | | if( e != 0 ) { e->UnrefObj(); } \ |
70 | | } |
71 | | #else |
72 | | |
73 | | #define _DECLARE_DL_SENTINEL(name) |
74 | | #define _IMPLEMENT_DL_SENTINEL(name) |
75 | | |
76 | | #endif // wxUSE_NESTED_CLASSES |
77 | | |
78 | | #define wxDECLARE_PLUGGABLE_CLASS(name) \ |
79 | | wxDECLARE_DYNAMIC_CLASS(name); _DECLARE_DL_SENTINEL(name, WXDLLIMPEXP_CORE) |
80 | | #define wxDECLARE_ABSTRACT_PLUGGABLE_CLASS(name) \ |
81 | | wxDECLARE_ABSTRACT_CLASS(name); _DECLARE_DL_SENTINEL(name, WXDLLIMPEXP_CORE) |
82 | | |
83 | | #define wxDECLARE_USER_EXPORTED_PLUGGABLE_CLASS(name, usergoo) \ |
84 | | wxDECLARE_DYNAMIC_CLASS(name); _DECLARE_DL_SENTINEL(name, usergoo) |
85 | | #define wxDECLARE_USER_EXPORTED_ABSTRACT_PLUGGABLE_CLASS(name, usergoo) \ |
86 | | wxDECLARE_ABSTRACT_CLASS(name); _DECLARE_DL_SENTINEL(name, usergoo) |
87 | | |
88 | | #define wxIMPLEMENT_PLUGGABLE_CLASS(name, basename) \ |
89 | | wxIMPLEMENT_DYNAMIC_CLASS(name, basename) _IMPLEMENT_DL_SENTINEL(name) |
90 | | #define wxIMPLEMENT_PLUGGABLE_CLASS2(name, basename1, basename2) \ |
91 | | wxIMPLEMENT_DYNAMIC_CLASS2(name, basename1, basename2) _IMPLEMENT_DL_SENTINEL(name) |
92 | | #define wxIMPLEMENT_ABSTRACT_PLUGGABLE_CLASS(name, basename) \ |
93 | | wxIMPLEMENT_ABSTRACT_CLASS(name, basename) _IMPLEMENT_DL_SENTINEL(name) |
94 | | #define wxIMPLEMENT_ABSTRACT_PLUGGABLE_CLASS2(name, basename1, basename2) \ |
95 | | wxIMPLEMENT_ABSTRACT_CLASS2(name, basename1, basename2) _IMPLEMENT_DL_SENTINEL(name) |
96 | | |
97 | | #define wxIMPLEMENT_USER_EXPORTED_PLUGGABLE_CLASS(name, basename) \ |
98 | | wxIMPLEMENT_PLUGGABLE_CLASS(name, basename) |
99 | | #define wxIMPLEMENT_USER_EXPORTED_PLUGGABLE_CLASS2(name, basename1, basename2) \ |
100 | | wxIMPLEMENT_PLUGGABLE_CLASS2(name, basename1, basename2) |
101 | | #define wxIMPLEMENT_USER_EXPORTED_ABSTRACT_PLUGGABLE_CLASS(name, basename) \ |
102 | | wxIMPLEMENT_ABSTRACT_PLUGGABLE_CLASS(name, basename) |
103 | | #define wxIMPLEMENT_USER_EXPORTED_ABSTRACT_PLUGGABLE_CLASS2(name, basename1, basename2) \ |
104 | | wxIMPLEMENT_ABSTRACT_PLUGGABLE_CLASS2(name, basename1, basename2) |
105 | | |
106 | 0 | #define wxCLASSINFO(name) (&name::ms_classInfo) |
107 | | |
108 | | #define wxIS_KIND_OF(obj, className) obj->IsKindOf(&className::ms_classInfo) |
109 | | |
110 | | // Just seems a bit nicer-looking (pretend it's not a macro) |
111 | | #define wxIsKindOf(obj, className) obj->IsKindOf(&className::ms_classInfo) |
112 | | |
113 | | // this cast does some more checks at compile time as it uses static_cast |
114 | | // internally |
115 | | // |
116 | | // note that it still has different semantics from dynamic_cast<> and so can't |
117 | | // be replaced by it as long as there are any compilers not supporting it |
118 | | #define wxDynamicCast(obj, className) \ |
119 | | (static_cast<className*>(wxCheckDynamicCast( \ |
120 | | const_cast<wxObject *>(static_cast<const wxObject *>(obj)), \ |
121 | | &className::ms_classInfo))) |
122 | | |
123 | | // The 'this' pointer is always true, so use this version |
124 | | // to cast the this pointer and avoid compiler warnings. |
125 | | #define wxDynamicCastThis(className) \ |
126 | | (IsKindOf(&className::ms_classInfo) ? (className*)this : nullptr) |
127 | | |
128 | | template <class T> |
129 | | inline T *wxCheckCast(const void *ptr) |
130 | 0 | { |
131 | 0 | wxASSERT_MSG( wxDynamicCast(ptr, T), "wxStaticCast() used incorrectly" ); |
132 | 0 | return const_cast<T *>(static_cast<const T *>(ptr)); |
133 | 0 | } |
134 | | |
135 | 0 | #define wxStaticCast(obj, className) wxCheckCast<className>(obj) |
136 | | |
137 | | // ---------------------------------------------------------------------------- |
138 | | // Compatibility macro aliases DECLARE group |
139 | | // ---------------------------------------------------------------------------- |
140 | | // deprecated variants _not_ requiring a semicolon after them and without wx prefix. |
141 | | // (note that also some wx-prefixed macro do _not_ require a semicolon because |
142 | | // it's not always possible to force the compiler to require it) |
143 | | |
144 | | #define DECLARE_ABSTRACT_CLASS(n) wxDECLARE_ABSTRACT_CLASS(n); |
145 | | #define DECLARE_DYNAMIC_CLASS_NO_ASSIGN(n) wxDECLARE_DYNAMIC_CLASS_NO_ASSIGN(n); |
146 | | #define DECLARE_DYNAMIC_CLASS_NO_COPY(n) wxDECLARE_DYNAMIC_CLASS_NO_COPY(n); |
147 | | #define DECLARE_DYNAMIC_CLASS(n) wxDECLARE_DYNAMIC_CLASS(n); |
148 | | #define DECLARE_CLASS(n) wxDECLARE_CLASS(n); |
149 | | |
150 | | #define DECLARE_PLUGGABLE_CLASS(n) wxDECLARE_PLUGGABLE_CLASS(n); |
151 | | #define DECLARE_ABSTRACT_PLUGGABLE_CLASS(n) wxDECLARE_ABSTRACT_PLUGGABLE_CLASS(n); |
152 | | #define DECLARE_USER_EXPORTED_PLUGGABLE_CLASS(n,u) wxDECLARE_USER_EXPORTED_PLUGGABLE_CLASS(n,u); |
153 | | #define DECLARE_USER_EXPORTED_ABSTRACT_PLUGGABLE_CLASS(n,u) wxDECLARE_USER_EXPORTED_ABSTRACT_PLUGGABLE_CLASS(n,u); |
154 | | |
155 | | // ---------------------------------------------------------------------------- |
156 | | // wxRefCounter: ref counted data "manager" |
157 | | // ---------------------------------------------------------------------------- |
158 | | |
159 | | class WXDLLIMPEXP_BASE wxRefCounter |
160 | | { |
161 | | public: |
162 | 0 | wxRefCounter() { m_count = 1; } |
163 | | |
164 | 0 | int GetRefCount() const { return m_count; } |
165 | | |
166 | 0 | void IncRef() { m_count++; } |
167 | | void DecRef(); |
168 | | |
169 | | protected: |
170 | | // this object should never be destroyed directly but only as a |
171 | | // result of a DecRef() call: |
172 | 0 | virtual ~wxRefCounter() = default; |
173 | | |
174 | | private: |
175 | | // our refcount: |
176 | | int m_count; |
177 | | |
178 | | // It doesn't make sense to copy the reference counted objects, a new ref |
179 | | // counter should be created for a new object instead and compilation |
180 | | // errors in the code using wxRefCounter due to the lack of copy ctor often |
181 | | // indicate a problem, e.g. a forgotten copy ctor implementation somewhere. |
182 | | wxDECLARE_NO_COPY_CLASS(wxRefCounter); |
183 | | }; |
184 | | |
185 | | // ---------------------------------------------------------------------------- |
186 | | // wxObjectRefData: ref counted data meant to be stored in wxObject |
187 | | // ---------------------------------------------------------------------------- |
188 | | |
189 | | typedef wxRefCounter wxObjectRefData; |
190 | | |
191 | | // ---------------------------------------------------------------------------- |
192 | | // wxObjectDataPtr: helper class to avoid memleaks because of missing calls |
193 | | // to wxObjectRefData::DecRef |
194 | | // ---------------------------------------------------------------------------- |
195 | | |
196 | | template <class T> |
197 | | class wxObjectDataPtr |
198 | | { |
199 | | public: |
200 | | typedef T element_type; |
201 | | |
202 | | explicit wxObjectDataPtr(T *ptr = nullptr) : m_ptr(ptr) {} |
203 | | |
204 | | // copy ctor |
205 | | wxObjectDataPtr(const wxObjectDataPtr<T> &tocopy) |
206 | | : m_ptr(tocopy.m_ptr) |
207 | | { |
208 | | if (m_ptr) |
209 | | m_ptr->IncRef(); |
210 | | } |
211 | | |
212 | | // generalized copy ctor: U must be convertible to T |
213 | | template <typename U> |
214 | | wxObjectDataPtr(const wxObjectDataPtr<U> &tocopy) |
215 | | : m_ptr(tocopy.get()) |
216 | | { |
217 | | if (m_ptr) |
218 | | m_ptr->IncRef(); |
219 | | } |
220 | | |
221 | | ~wxObjectDataPtr() |
222 | | { |
223 | | if (m_ptr) |
224 | | m_ptr->DecRef(); |
225 | | } |
226 | | |
227 | 0 | T *get() const { return m_ptr; } |
228 | | |
229 | | bool operator==(const wxObjectDataPtr<T>& other) const |
230 | | { |
231 | | return m_ptr == other.m_ptr; |
232 | | } |
233 | | |
234 | | bool operator!=(const wxObjectDataPtr<T>& other) const |
235 | | { |
236 | | return !(*this == other); |
237 | | } |
238 | | |
239 | | // test for pointer validity: defining conversion to unspecified_bool_type |
240 | | // and not more obvious bool to avoid implicit conversions to integer types |
241 | | typedef T *(wxObjectDataPtr<T>::*unspecified_bool_type)() const; |
242 | | operator unspecified_bool_type() const |
243 | | { |
244 | | return m_ptr ? &wxObjectDataPtr<T>::get : nullptr; |
245 | | } |
246 | | |
247 | | T& operator*() const |
248 | | { |
249 | | wxASSERT(m_ptr != nullptr); |
250 | | return *(m_ptr); |
251 | | } |
252 | | |
253 | | T *operator->() const |
254 | | { |
255 | | wxASSERT(m_ptr != nullptr); |
256 | | return get(); |
257 | | } |
258 | | |
259 | | void reset(T *ptr) |
260 | | { |
261 | | if (m_ptr) |
262 | | m_ptr->DecRef(); |
263 | | m_ptr = ptr; |
264 | | } |
265 | | |
266 | | T* release() |
267 | | { |
268 | | T* const ptr = m_ptr; |
269 | | m_ptr = nullptr; |
270 | | return ptr; |
271 | | } |
272 | | |
273 | | wxObjectDataPtr& operator=(const wxObjectDataPtr &tocopy) |
274 | 0 | { |
275 | 0 | // Take care to increment the reference first to ensure correct |
276 | 0 | // behaviour in case of self-assignment. |
277 | 0 | T* const ptr = tocopy.m_ptr; |
278 | 0 | if (ptr) |
279 | 0 | ptr->IncRef(); |
280 | 0 | if (m_ptr) |
281 | 0 | m_ptr->DecRef(); |
282 | 0 | m_ptr = ptr; |
283 | 0 | return *this; |
284 | 0 | } |
285 | | |
286 | | template <typename U> |
287 | | wxObjectDataPtr& operator=(const wxObjectDataPtr<U> &tocopy) |
288 | | { |
289 | | T* const ptr = tocopy.get(); |
290 | | if (ptr) |
291 | | ptr->IncRef(); |
292 | | if (m_ptr) |
293 | | m_ptr->DecRef(); |
294 | | m_ptr = ptr; |
295 | | return *this; |
296 | | } |
297 | | |
298 | | wxObjectDataPtr& operator=(T *ptr) |
299 | | { |
300 | | if (m_ptr) |
301 | | m_ptr->DecRef(); |
302 | | m_ptr = ptr; |
303 | | return *this; |
304 | | } |
305 | | |
306 | | private: |
307 | | T *m_ptr; |
308 | | }; |
309 | | |
310 | | // ---------------------------------------------------------------------------- |
311 | | // wxObject: the root class of wxWidgets object hierarchy |
312 | | // ---------------------------------------------------------------------------- |
313 | | |
314 | | class WXDLLIMPEXP_BASE wxObject |
315 | | { |
316 | | #if wxUSE_EXTENDED_RTTI |
317 | | wxDECLARE_DYNAMIC_CLASS(wxObject); |
318 | | #endif |
319 | | |
320 | | public: |
321 | 16.5k | wxObject() { m_refData = nullptr; } |
322 | 32.2k | virtual ~wxObject() { UnRef(); } |
323 | | |
324 | | wxObject(const wxObject& other) |
325 | 15.6k | { |
326 | 15.6k | m_refData = other.m_refData; |
327 | 15.6k | if (m_refData) |
328 | 0 | m_refData->IncRef(); |
329 | 15.6k | } |
330 | | |
331 | | wxObject& operator=(const wxObject& other) |
332 | 0 | { |
333 | 0 | if ( this != &other ) |
334 | 0 | { |
335 | 0 | Ref(other); |
336 | 0 | } |
337 | 0 | return *this; |
338 | 0 | } |
339 | | |
340 | | bool IsKindOf(const wxClassInfo *info) const; |
341 | | |
342 | | // Turn on the correct set of new and delete operators |
343 | | |
344 | | #ifdef _WX_WANT_NEW_SIZET_WXCHAR_INT |
345 | | void *operator new ( size_t size, const wxChar *fileName = nullptr, int lineNum = 0 ); |
346 | | #endif |
347 | | |
348 | | #ifdef _WX_WANT_DELETE_VOID |
349 | | void operator delete ( void * buf ); |
350 | | #endif |
351 | | |
352 | | #ifdef _WX_WANT_DELETE_VOID_WXCHAR_INT |
353 | | void operator delete ( void *buf, const wxChar*, int ); |
354 | | #endif |
355 | | |
356 | | #ifdef _WX_WANT_ARRAY_NEW_SIZET_WXCHAR_INT |
357 | | void *operator new[] ( size_t size, const wxChar *fileName = nullptr, int lineNum = 0 ); |
358 | | #endif |
359 | | |
360 | | #ifdef _WX_WANT_ARRAY_DELETE_VOID |
361 | | void operator delete[] ( void *buf ); |
362 | | #endif |
363 | | |
364 | | #ifdef _WX_WANT_ARRAY_DELETE_VOID_WXCHAR_INT |
365 | | void operator delete[] (void* buf, const wxChar*, int ); |
366 | | #endif |
367 | | |
368 | | // ref counted data handling methods |
369 | | |
370 | | // get/set |
371 | 0 | wxObjectRefData *GetRefData() const { return m_refData; } |
372 | 0 | void SetRefData(wxObjectRefData *data) { m_refData = data; } |
373 | | |
374 | | // make a 'clone' of the object |
375 | | void Ref(const wxObject& clone); |
376 | | |
377 | | // destroy a reference |
378 | | void UnRef(); |
379 | | |
380 | | // Make sure this object has only one reference |
381 | 0 | void UnShare() { AllocExclusive(); } |
382 | | |
383 | | // check if this object references the same data as the other one |
384 | 0 | bool IsSameAs(const wxObject& o) const { return m_refData == o.m_refData; } |
385 | | |
386 | | #if !wxUSE_EXTENDED_RTTI |
387 | | virtual wxClassInfo* GetClassInfo() const; |
388 | | |
389 | | // RTTI information, usually declared by wxDECLARE_DYNAMIC_CLASS() or |
390 | | // similar, but done manually for the hierarchy root. Note that it's public |
391 | | // for compatibility reasons, but shouldn't be accessed directly. |
392 | | static wxClassInfo ms_classInfo; |
393 | | #endif |
394 | | |
395 | | protected: |
396 | | // ensure that our data is not shared with anybody else: if we have no |
397 | | // data, it is created using CreateRefData() below, if we have shared data |
398 | | // it is copied using CloneRefData(), otherwise nothing is done |
399 | | void AllocExclusive(); |
400 | | |
401 | | // both methods must be implemented if AllocExclusive() is used, not pure |
402 | | // virtual only because of the backwards compatibility reasons |
403 | | |
404 | | // create a new m_refData |
405 | | virtual wxObjectRefData *CreateRefData() const; |
406 | | |
407 | | // create a new m_refData initialized with the given one |
408 | | wxNODISCARD virtual wxObjectRefData *CloneRefData(const wxObjectRefData *data) const; |
409 | | |
410 | | wxObjectRefData *m_refData; |
411 | | }; |
412 | | |
413 | | inline wxObject *wxCheckDynamicCast(wxObject *obj, wxClassInfo *classInfo) |
414 | 0 | { |
415 | 0 | return obj && obj->GetClassInfo()->IsKindOf(classInfo) ? obj : nullptr; |
416 | 0 | } |
417 | | |
418 | | #include "wx/xti2.h" |
419 | | |
420 | | // ---------------------------------------------------------------------------- |
421 | | // Compatibility macro aliases IMPLEMENT group |
422 | | // ---------------------------------------------------------------------------- |
423 | | |
424 | | // deprecated variants _not_ requiring a semicolon after them and without wx prefix. |
425 | | // (note that also some wx-prefixed macro do _not_ require a semicolon because |
426 | | // it's not always possible to force the compiler to require it) |
427 | | |
428 | | #define IMPLEMENT_DYNAMIC_CLASS(n,b) wxIMPLEMENT_DYNAMIC_CLASS(n,b) |
429 | | #define IMPLEMENT_DYNAMIC_CLASS2(n,b1,b2) wxIMPLEMENT_DYNAMIC_CLASS2(n,b1,b2) |
430 | | #define IMPLEMENT_ABSTRACT_CLASS(n,b) wxIMPLEMENT_ABSTRACT_CLASS(n,b) |
431 | | #define IMPLEMENT_ABSTRACT_CLASS2(n,b1,b2) wxIMPLEMENT_ABSTRACT_CLASS2(n,b1,b2) |
432 | | #define IMPLEMENT_CLASS(n,b) wxIMPLEMENT_CLASS(n,b) |
433 | | #define IMPLEMENT_CLASS2(n,b1,b2) wxIMPLEMENT_CLASS2(n,b1,b2) |
434 | | |
435 | | #define IMPLEMENT_PLUGGABLE_CLASS(n,b) wxIMPLEMENT_PLUGGABLE_CLASS(n,b) |
436 | | #define IMPLEMENT_PLUGGABLE_CLASS2(n,b,b2) wxIMPLEMENT_PLUGGABLE_CLASS2(n,b,b2) |
437 | | #define IMPLEMENT_ABSTRACT_PLUGGABLE_CLASS(n,b) wxIMPLEMENT_ABSTRACT_PLUGGABLE_CLASS(n,b) |
438 | | #define IMPLEMENT_ABSTRACT_PLUGGABLE_CLASS2(n,b,b2) wxIMPLEMENT_ABSTRACT_PLUGGABLE_CLASS2(n,b,b2) |
439 | | #define IMPLEMENT_USER_EXPORTED_PLUGGABLE_CLASS(n,b) wxIMPLEMENT_USER_EXPORTED_PLUGGABLE_CLASS(n,b) |
440 | | #define IMPLEMENT_USER_EXPORTED_PLUGGABLE_CLASS2(n,b,b2) wxIMPLEMENT_USER_EXPORTED_PLUGGABLE_CLASS2(n,b,b2) |
441 | | #define IMPLEMENT_USER_EXPORTED_ABSTRACT_PLUGGABLE_CLASS(n,b) wxIMPLEMENT_USER_EXPORTED_ABSTRACT_PLUGGABLE_CLASS(n,b) |
442 | | #define IMPLEMENT_USER_EXPORTED_ABSTRACT_PLUGGABLE_CLASS2(n,b,b2) wxIMPLEMENT_USER_EXPORTED_ABSTRACT_PLUGGABLE_CLASS2(n,b,b2) |
443 | | |
444 | | #define CLASSINFO(n) wxCLASSINFO(n) |
445 | | |
446 | | #endif // _WX_OBJECTH__ |