Coverage Report

Created: 2025-09-27 06:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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__