1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxObject class, plus run-time type information macros
4 // Author: Julian Smart
5 // Modified by: Ron Lee
8 // Copyright: (c) 1997 Julian Smart
9 // (c) 2001 Ron Lee <ron@debian.org>
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 #include "wx/memory.h"
22 // based on the value of wxUSE_EXTENDED_RTTI symbol,
23 // only one of the RTTI system will be compiled:
24 // - the "old" one (defined by rtti.h) or
25 // - the "new" one (defined by xti.h)
29 // -----------------------------------
30 // for pluggable classes
31 // -----------------------------------
33 // NOTE: this should probably be the very first statement
34 // in the class declaration so wxPluginSentinel is
35 // the first member initialised and the last destroyed.
37 // _DECLARE_DL_SENTINEL(name) wxPluginSentinel m_pluginsentinel;
39 #if wxUSE_NESTED_CLASSES
41 #define _DECLARE_DL_SENTINEL(name, exportdecl) \
42 class exportdecl name##PluginSentinel { \
44 static const wxString sm_className; \
46 name##PluginSentinel(); \
47 ~name##PluginSentinel(); \
49 name##PluginSentinel m_pluginsentinel
51 #define _IMPLEMENT_DL_SENTINEL(name) \
52 const wxString name::name##PluginSentinel::sm_className(#name); \
53 name::name##PluginSentinel::name##PluginSentinel() { \
54 wxPluginLibrary *e = (wxPluginLibrary*) wxPluginLibrary::ms_classes.Get(#name); \
55 if( e != 0 ) { e->RefObj(); } \
57 name::name##PluginSentinel::~name##PluginSentinel() { \
58 wxPluginLibrary *e = (wxPluginLibrary*) wxPluginLibrary::ms_classes.Get(#name); \
59 if( e != 0 ) { e->UnrefObj(); } \
63 #define _DECLARE_DL_SENTINEL(name)
64 #define _IMPLEMENT_DL_SENTINEL(name)
66 #endif // wxUSE_NESTED_CLASSES
68 #define wxDECLARE_PLUGGABLE_CLASS(name) \
69 wxDECLARE_DYNAMIC_CLASS(name); _DECLARE_DL_SENTINEL(name, WXDLLIMPEXP_CORE)
70 #define wxDECLARE_ABSTRACT_PLUGGABLE_CLASS(name) \
71 wxDECLARE_ABSTRACT_CLASS(name); _DECLARE_DL_SENTINEL(name, WXDLLIMPEXP_CORE)
73 #define wxDECLARE_USER_EXPORTED_PLUGGABLE_CLASS(name, usergoo) \
74 wxDECLARE_DYNAMIC_CLASS(name); _DECLARE_DL_SENTINEL(name, usergoo)
75 #define wxDECLARE_USER_EXPORTED_ABSTRACT_PLUGGABLE_CLASS(name, usergoo) \
76 wxDECLARE_ABSTRACT_CLASS(name); _DECLARE_DL_SENTINEL(name, usergoo)
78 #define wxIMPLEMENT_PLUGGABLE_CLASS(name, basename) \
79 wxIMPLEMENT_DYNAMIC_CLASS(name, basename) _IMPLEMENT_DL_SENTINEL(name)
80 #define wxIMPLEMENT_PLUGGABLE_CLASS2(name, basename1, basename2) \
81 wxIMPLEMENT_DYNAMIC_CLASS2(name, basename1, basename2) _IMPLEMENT_DL_SENTINEL(name)
82 #define wxIMPLEMENT_ABSTRACT_PLUGGABLE_CLASS(name, basename) \
83 wxIMPLEMENT_ABSTRACT_CLASS(name, basename) _IMPLEMENT_DL_SENTINEL(name)
84 #define wxIMPLEMENT_ABSTRACT_PLUGGABLE_CLASS2(name, basename1, basename2) \
85 wxIMPLEMENT_ABSTRACT_CLASS2(name, basename1, basename2) _IMPLEMENT_DL_SENTINEL(name)
87 #define wxIMPLEMENT_USER_EXPORTED_PLUGGABLE_CLASS(name, basename) \
88 wxIMPLEMENT_PLUGGABLE_CLASS(name, basename)
89 #define wxIMPLEMENT_USER_EXPORTED_PLUGGABLE_CLASS2(name, basename1, basename2) \
90 wxIMPLEMENT_PLUGGABLE_CLASS2(name, basename1, basename2)
91 #define wxIMPLEMENT_USER_EXPORTED_ABSTRACT_PLUGGABLE_CLASS(name, basename) \
92 wxIMPLEMENT_ABSTRACT_PLUGGABLE_CLASS(name, basename)
93 #define wxIMPLEMENT_USER_EXPORTED_ABSTRACT_PLUGGABLE_CLASS2(name, basename1, basename2) \
94 wxIMPLEMENT_ABSTRACT_PLUGGABLE_CLASS2(name, basename1, basename2)
96 #define wxCLASSINFO(name) (&name::ms_classInfo)
98 #define wxIS_KIND_OF(obj, className) obj->IsKindOf(&className::ms_classInfo)
100 // Just seems a bit nicer-looking (pretend it's not a macro)
101 #define wxIsKindOf(obj, className) obj->IsKindOf(&className::ms_classInfo)
103 // this cast does some more checks at compile time as it uses static_cast
106 // note that it still has different semantics from dynamic_cast<> and so can't
107 // be replaced by it as long as there are any compilers not supporting it
108 #define wxDynamicCast(obj, className) \
109 ((className *) wxCheckDynamicCast( \
110 const_cast<wxObject *>(static_cast<const wxObject *>(\
111 const_cast<className *>(static_cast<const className *>(obj)))), \
112 &className::ms_classInfo))
114 // The 'this' pointer is always true, so use this version
115 // to cast the this pointer and avoid compiler warnings.
116 #define wxDynamicCastThis(className) \
117 (IsKindOf(&className::ms_classInfo) ? (className *)(this) : (className *)0)
119 // FIXME-VC6: dummy argument needed because VC6 doesn't support explicitly
120 // choosing the template function to call
122 inline T
*wxCheckCast(const void *ptr
, T
* = NULL
)
124 wxASSERT_MSG( wxDynamicCast(ptr
, T
), "wxStaticCast() used incorrectly" );
125 return const_cast<T
*>(static_cast<const T
*>(ptr
));
128 #define wxStaticCast(obj, className) wxCheckCast((obj), (className *)NULL)
130 // ----------------------------------------------------------------------------
131 // set up memory debugging macros
132 // ----------------------------------------------------------------------------
135 Which new/delete operator variants do we want?
137 _WX_WANT_NEW_SIZET_WXCHAR_INT = void *operator new (size_t size, wxChar *fileName = 0, int lineNum = 0)
138 _WX_WANT_DELETE_VOID = void operator delete (void * buf)
139 _WX_WANT_DELETE_VOID_CONSTCHAR_SIZET = void operator delete (void *buf, const char *_fname, size_t _line)
140 _WX_WANT_DELETE_VOID_WXCHAR_INT = void operator delete(void *buf, wxChar*, int)
141 _WX_WANT_ARRAY_NEW_SIZET_WXCHAR_INT = void *operator new[] (size_t size, wxChar *fileName , int lineNum = 0)
142 _WX_WANT_ARRAY_DELETE_VOID = void operator delete[] (void *buf)
143 _WX_WANT_ARRAY_DELETE_VOID_WXCHAR_INT = void operator delete[] (void* buf, wxChar*, int )
146 #if wxUSE_MEMORY_TRACING
148 // All compilers get this one
149 #define _WX_WANT_NEW_SIZET_WXCHAR_INT
151 // Everyone except Visage gets the next one
152 #ifndef __VISAGECPP__
153 #define _WX_WANT_DELETE_VOID
156 // Only visage gets this one under the correct circumstances
157 #if defined(__VISAGECPP__) && __DEBUG_ALLOC__
158 #define _WX_WANT_DELETE_VOID_CONSTCHAR_SIZET
161 // Only VC++ 6 and CodeWarrior get overloaded delete that matches new
162 #if (defined(__VISUALC__) && (__VISUALC__ >= 1200)) || \
163 (defined(__MWERKS__) && (__MWERKS__ >= 0x2400))
164 #define _WX_WANT_DELETE_VOID_WXCHAR_INT
167 // Now see who (if anyone) gets the array memory operators
168 #if wxUSE_ARRAY_MEMORY_OPERATORS
170 // Everyone except Visual C++ (cause problems for VC++ - crashes)
171 #if !defined(__VISUALC__)
172 #define _WX_WANT_ARRAY_NEW_SIZET_WXCHAR_INT
175 // Everyone except Visual C++ (cause problems for VC++ - crashes)
176 #if !defined(__VISUALC__)
177 #define _WX_WANT_ARRAY_DELETE_VOID
180 // Only CodeWarrior 6 or higher
181 #if defined(__MWERKS__) && (__MWERKS__ >= 0x2400)
182 #define _WX_WANT_ARRAY_DELETE_VOID_WXCHAR_INT
185 #endif // wxUSE_ARRAY_MEMORY_OPERATORS
187 #endif // wxUSE_MEMORY_TRACING
189 // ----------------------------------------------------------------------------
190 // wxRefCounter: ref counted data "manager"
191 // ----------------------------------------------------------------------------
193 class WXDLLIMPEXP_BASE wxRefCounter
196 wxRefCounter() { m_count
= 1; }
198 int GetRefCount() const { return m_count
; }
200 void IncRef() { m_count
++; }
204 // this object should never be destroyed directly but only as a
205 // result of a DecRef() call:
206 virtual ~wxRefCounter() { }
212 // It doesn't make sense to copy the reference counted objects, a new ref
213 // counter should be created for a new object instead and compilation
214 // errors in the code using wxRefCounter due to the lack of copy ctor often
215 // indicate a problem, e.g. a forgotten copy ctor implementation somewhere.
216 wxDECLARE_NO_COPY_CLASS(wxRefCounter
);
219 // ----------------------------------------------------------------------------
220 // wxObjectRefData: ref counted data meant to be stored in wxObject
221 // ----------------------------------------------------------------------------
223 typedef wxRefCounter wxObjectRefData
;
226 // ----------------------------------------------------------------------------
227 // wxObjectDataPtr: helper class to avoid memleaks because of missing calls
228 // to wxObjectRefData::DecRef
229 // ----------------------------------------------------------------------------
232 class wxObjectDataPtr
235 typedef T element_type
;
237 wxEXPLICIT
wxObjectDataPtr(T
*ptr
= NULL
) : m_ptr(ptr
) {}
240 wxObjectDataPtr(const wxObjectDataPtr
<T
> &tocopy
)
241 : m_ptr(tocopy
.m_ptr
)
253 T
*get() const { return m_ptr
; }
255 // test for pointer validity: defining conversion to unspecified_bool_type
256 // and not more obvious bool to avoid implicit conversions to integer types
257 typedef T
*(wxObjectDataPtr
<T
>::*unspecified_bool_type
)() const;
258 operator unspecified_bool_type() const
260 return m_ptr
? &wxObjectDataPtr
<T
>::get
: NULL
;
265 wxASSERT(m_ptr
!= NULL
);
269 T
*operator->() const
271 wxASSERT(m_ptr
!= NULL
);
282 wxObjectDataPtr
& operator=(const wxObjectDataPtr
&tocopy
)
286 m_ptr
= tocopy
.m_ptr
;
292 wxObjectDataPtr
& operator=(T
*ptr
)
304 // ----------------------------------------------------------------------------
305 // wxObject: the root class of wxWidgets object hierarchy
306 // ----------------------------------------------------------------------------
308 class WXDLLIMPEXP_BASE wxObject
310 wxDECLARE_ABSTRACT_CLASS(wxObject
);
313 wxObject() { m_refData
= NULL
; }
314 virtual ~wxObject() { UnRef(); }
316 wxObject(const wxObject
& other
)
318 m_refData
= other
.m_refData
;
323 wxObject
& operator=(const wxObject
& other
)
325 if ( this != &other
)
332 bool IsKindOf(const wxClassInfo
*info
) const;
335 // Turn on the correct set of new and delete operators
337 #ifdef _WX_WANT_NEW_SIZET_WXCHAR_INT
338 void *operator new ( size_t size
, const wxChar
*fileName
= NULL
, int lineNum
= 0 );
341 #ifdef _WX_WANT_DELETE_VOID
342 void operator delete ( void * buf
);
345 #ifdef _WX_WANT_DELETE_VOID_CONSTCHAR_SIZET
346 void operator delete ( void *buf
, const char *_fname
, size_t _line
);
349 #ifdef _WX_WANT_DELETE_VOID_WXCHAR_INT
350 void operator delete ( void *buf
, const wxChar
*, int );
353 #ifdef _WX_WANT_ARRAY_NEW_SIZET_WXCHAR_INT
354 void *operator new[] ( size_t size
, const wxChar
*fileName
= NULL
, int lineNum
= 0 );
357 #ifdef _WX_WANT_ARRAY_DELETE_VOID
358 void operator delete[] ( void *buf
);
361 #ifdef _WX_WANT_ARRAY_DELETE_VOID_WXCHAR_INT
362 void operator delete[] (void* buf
, const wxChar
*, int );
365 // ref counted data handling methods
368 wxObjectRefData
*GetRefData() const { return m_refData
; }
369 void SetRefData(wxObjectRefData
*data
) { m_refData
= data
; }
371 // make a 'clone' of the object
372 void Ref(const wxObject
& clone
);
374 // destroy a reference
377 // Make sure this object has only one reference
378 void UnShare() { AllocExclusive(); }
380 // check if this object references the same data as the other one
381 bool IsSameAs(const wxObject
& o
) const { return m_refData
== o
.m_refData
; }
384 // ensure that our data is not shared with anybody else: if we have no
385 // data, it is created using CreateRefData() below, if we have shared data
386 // it is copied using CloneRefData(), otherwise nothing is done
387 void AllocExclusive();
389 // both methods must be implemented if AllocExclusive() is used, not pure
390 // virtual only because of the backwards compatibility reasons
392 // create a new m_refData
393 virtual wxObjectRefData
*CreateRefData() const;
395 // create a new m_refData initialized with the given one
396 virtual wxObjectRefData
*CloneRefData(const wxObjectRefData
*data
) const;
398 wxObjectRefData
*m_refData
;
401 inline wxObject
*wxCheckDynamicCast(wxObject
*obj
, wxClassInfo
*classInfo
)
403 return obj
&& obj
->GetClassInfo()->IsKindOf(classInfo
) ? obj
: NULL
;
406 #if wxUSE_EXTENDED_RTTI
407 class WXDLLIMPEXP_BASE wxDynamicObject
: public wxObject
409 friend class WXDLLIMPEXP_FWD_BASE wxDynamicClassInfo
;
411 // instantiates this object with an instance of its superclass
412 wxDynamicObject(wxObject
* superClassInstance
, const wxDynamicClassInfo
*info
) ;
413 virtual ~wxDynamicObject();
415 void SetProperty (const wxChar
*propertyName
, const wxxVariant
&value
);
416 wxxVariant
GetProperty (const wxChar
*propertyName
) const ;
418 // get the runtime identity of this object
419 wxClassInfo
*GetClassInfo() const
422 return (wxClassInfo
*) m_classInfo
;
424 wxDynamicClassInfo
*nonconst
= const_cast<wxDynamicClassInfo
*>(m_classInfo
);
425 return static_cast<wxClassInfo
*>(nonconst
);
429 wxObject
* GetSuperClassInstance() const
431 return m_superClassInstance
;
434 // removes an existing runtime-property
435 void RemoveProperty( const wxChar
*propertyName
) ;
437 // renames an existing runtime-property
438 void RenameProperty( const wxChar
*oldPropertyName
, const wxChar
*newPropertyName
) ;
440 wxObject
*m_superClassInstance
;
441 const wxDynamicClassInfo
*m_classInfo
;
442 struct wxDynamicObjectInternal
;
443 wxDynamicObjectInternal
*m_data
;
447 // ----------------------------------------------------------------------------
448 // more debugging macros
449 // ----------------------------------------------------------------------------
451 #if wxUSE_DEBUG_NEW_ALWAYS
452 #define WXDEBUG_NEW new(__TFILE__,__LINE__)
454 #if wxUSE_GLOBAL_MEMORY_OPERATORS
455 #define new WXDEBUG_NEW
456 #elif defined(__VISUALC__)
457 // Including this file redefines new and allows leak reports to
458 // contain line numbers
459 #include "wx/msw/msvcrt.h"
461 #endif // wxUSE_DEBUG_NEW_ALWAYS
463 // ----------------------------------------------------------------------------
464 // Compatibility macro aliases
465 // ----------------------------------------------------------------------------
467 // deprecated variants _not_ requiring a semicolon after them and without wx prefix.
468 // (note that also some wx-prefixed macro do _not_ require a semicolon because
469 // it's not always possible to force the compire to require it)
471 #define DECLARE_CLASS_INFO_ITERATORS() wxDECLARE_CLASS_INFO_ITERATORS();
472 #define DECLARE_ABSTRACT_CLASS(n) wxDECLARE_ABSTRACT_CLASS(n);
473 #define DECLARE_DYNAMIC_CLASS_NO_ASSIGN(n) wxDECLARE_DYNAMIC_CLASS_NO_ASSIGN(n);
474 #define DECLARE_DYNAMIC_CLASS_NO_COPY(n) wxDECLARE_DYNAMIC_CLASS_NO_COPY(n);
475 #define DECLARE_DYNAMIC_CLASS(n) wxDECLARE_DYNAMIC_CLASS(n);
476 #define DECLARE_CLASS(n) wxDECLARE_CLASS(n);
478 #define IMPLEMENT_DYNAMIC_CLASS(n,b) wxIMPLEMENT_DYNAMIC_CLASS(n,b)
479 #define IMPLEMENT_DYNAMIC_CLASS2(n,b1,b2) wxIMPLEMENT_DYNAMIC_CLASS2(n,b1,b2)
480 #define IMPLEMENT_ABSTRACT_CLASS(n,b) wxIMPLEMENT_ABSTRACT_CLASS(n,b)
481 #define IMPLEMENT_ABSTRACT_CLASS2(n,b1,b2) wxIMPLEMENT_ABSTRACT_CLASS2(n,b1,b2)
482 #define IMPLEMENT_CLASS(n,b) wxIMPLEMENT_CLASS(n,b)
483 #define IMPLEMENT_CLASS2(n,b1,b2) wxIMPLEMENT_CLASS2(n,b1,b2)
485 #define DECLARE_PLUGGABLE_CLASS(n) wxDECLARE_PLUGGABLE_CLASS(n);
486 #define DECLARE_ABSTRACT_PLUGGABLE_CLASS(n) wxDECLARE_ABSTRACT_PLUGGABLE_CLASS(n);
487 #define DECLARE_USER_EXPORTED_PLUGGABLE_CLASS(n,u) wxDECLARE_USER_EXPORTED_PLUGGABLE_CLASS(n,u);
488 #define DECLARE_USER_EXPORTED_ABSTRACT_PLUGGABLE_CLASS(n,u) wxDECLARE_USER_EXPORTED_ABSTRACT_PLUGGABLE_CLASS(n,u);
490 #define IMPLEMENT_PLUGGABLE_CLASS(n,b) wxIMPLEMENT_PLUGGABLE_CLASS(n,b)
491 #define IMPLEMENT_PLUGGABLE_CLASS2(n,b,b2) wxIMPLEMENT_PLUGGABLE_CLASS2(n,b,b2)
492 #define IMPLEMENT_ABSTRACT_PLUGGABLE_CLASS(n,b) wxIMPLEMENT_ABSTRACT_PLUGGABLE_CLASS(n,b)
493 #define IMPLEMENT_ABSTRACT_PLUGGABLE_CLASS2(n,b,b2) wxIMPLEMENT_ABSTRACT_PLUGGABLE_CLASS2(n,b,b2)
494 #define IMPLEMENT_USER_EXPORTED_PLUGGABLE_CLASS(n,b) wxIMPLEMENT_USER_EXPORTED_PLUGGABLE_CLASS(n,b)
495 #define IMPLEMENT_USER_EXPORTED_PLUGGABLE_CLASS2(n,b,b2) wxIMPLEMENT_USER_EXPORTED_PLUGGABLE_CLASS2(n,b,b2)
496 #define IMPLEMENT_USER_EXPORTED_ABSTRACT_PLUGGABLE_CLASS(n,b) wxIMPLEMENT_USER_EXPORTED_ABSTRACT_PLUGGABLE_CLASS(n,b)
497 #define IMPLEMENT_USER_EXPORTED_ABSTRACT_PLUGGABLE_CLASS2(n,b,b2) wxIMPLEMENT_USER_EXPORTED_ABSTRACT_PLUGGABLE_CLASS2(n,b,b2)
499 #define CLASSINFO(n) wxCLASSINFO(n)
501 #endif // _WX_OBJECTH__