File: z105.html

package info (click to toggle)
ebook-dev-ggad 199908-2
  • links: PTS
  • area: main
  • in suites: woody
  • size: 2,264 kB
  • ctags: 1,163
  • sloc: sh: 44; makefile: 35
file content (303 lines) | stat: -rw-r--r-- 10,928 bytes parent folder | download | duplicates (2)
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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
  <head>
    <title>
      Type Checking and New Types
    </title>
    <meta name="GENERATOR" content=
    "Modular DocBook HTML Stylesheet Version 1.45">
    <link rel="HOME" title="GTK+ / Gnome Application Development"
    href="ggad.html">
    <link rel="UP" title="The GTK+ Object and Type System" href= 
    "cha-objects.html">
    <link rel="PREVIOUS" title="The GTK+ Object and Type System"
    href="cha-objects.html">
    <link rel="NEXT" title="Initializing a New Class" href= 
    "sec-classinit.html">
  </head>
  <body bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink= 
  "#840084" alink="#0000FF">
    <div class="NAVHEADER">
      <table width="100%" border="0" bgcolor="#ffffff" cellpadding= 
      "1" cellspacing="0">
        <tr>
          <th colspan="4" align="center">
            <font color="#000000" size="2">GTK+ / Gnome Application
            Development</font>
          </th>
        </tr>
        <tr>
          <td width="25%" bgcolor="#ffffff" align="left">
            <a href="cha-objects.html"><font color="#0000ff" size=
            "2"><b>&lt;&lt;&lt; Previous</b></font></a>
          </td>
          <td width="25%" colspan="2" bgcolor="#ffffff" align= 
          "center">
            <font color="#0000ff" size="2"><b><a href="ggad.html">
            <font color="#0000ff" size="2"><b>
            Home</b></font></a></b></font>
          </td>
          <td width="25%" bgcolor="#ffffff" align="right">
            <a href="sec-classinit.html"><font color="#0000ff"
            size="2"><b>Next &gt;&gt;&gt;</b></font></a>
          </td>
        </tr>
      </table>
    </div>
    <div class="SECT1">
      <h1 class="SECT1">
        <a name="Z105">Type Checking and New Types</a>
      </h1>
      <p>
        GTK+ has an extensive type system, which is to some extent
        independent of its object system. However, the object
        system makes use of the larger type system. Every object
        has a type, and every type has a unique integer identifier.
        When writing a <span class="STRUCTNAME">GtkObject</span>,
        it's customary to provide a function which returns the
        type's identifier.
      </p>
      <p>
        In the case of <tt class="CLASSNAME">GtkButton</tt>, the
        relevant function is:
      </p>
      <table border="0" bgcolor="#E0E0E0" width="100%">
        <tr>
          <td>
<pre class="PROGRAMLISTING">
&#13;GtkType gtk_button_get_type();&#13;
</pre>
          </td>
        </tr>
      </table>
      <p>
        The first time this function is invoked, it will register a
        <span class="STRUCTNAME">GtkButton</span> type with the
        object system, and in the process obtain a type identifier.
        On subsequent calls, the type identifier is simply
        returned. <span class="STRUCTNAME">GtkType</span> is a
        typedef (<span class="STRUCTNAME">unsigned int</span> is
        the actual type of GTK+'s type identifiers).
      </p>
      <p>
        The type system allows GTK+ to check the validity of casts.
        To facilitate this, objects customarily provide macros like
        these in their header file:
      </p>
      <table border="0" bgcolor="#E0E0E0" width="100%">
        <tr>
          <td>
<pre class="PROGRAMLISTING">
&#13;#define GTK_TYPE_BUTTON            (gtk_button_get_type ())
#define GTK_BUTTON(obj)            (GTK_CHECK_CAST ((obj), \
                                    GTK_TYPE_BUTTON, GtkButton))
#define GTK_BUTTON_CLASS(klass)    (GTK_CHECK_CLASS_CAST ((klass), \
                                    GTK_TYPE_BUTTON, GtkButtonClass))
#define GTK_IS_BUTTON(obj)         (GTK_CHECK_TYPE ((obj),  \
                                    GTK_TYPE_BUTTON))
#define GTK_IS_BUTTON_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass),  \
                                    GTK_TYPE_BUTTON))
&#13;
</pre>
          </td>
        </tr>
      </table>
      <p>
        Instead of simply casting an object, you can use the <tt
        class="FUNCTION">GTK_BUTTON()</tt> macro. If <tt class= 
        "FUNCTION">GTK_NO_CHECK_CASTS</tt> is defined, these macros
        are equivalent to simple casts. Otherwise, they retrieve
        the type of the object and compare it to the type you're
        attempting to cast to.
      </p>
      <p>
        GTK+ also provides convenient runtime type checking, with
        the <tt class="FUNCTION">GTK_IS_BUTTON()</tt> macro. This
        is often used in preconditions; for example, a function
        expecting a button as an argument might have this check at
        the beginning:
      </p>
      <table border="0" bgcolor="#E0E0E0" width="100%">
        <tr>
          <td>
<pre class="PROGRAMLISTING">
&#13;  g_return_if_fail(GTK_IS_BUTTON(widget));&#13;
</pre>
          </td>
        </tr>
      </table>
      <p>
        The GTK+ and Gnome library functions have many such checks.
        You can also use the macro to make certain code conditional
        on an object's type, though this is most likely a poor idea
        from a design standpoint.
      </p>
      <p>
        To give you an idea what sort of information GTK+ stores
        about each object type, here's the implementation of <tt
        class="FUNCTION">gtk_button_get_type()</tt>:
      </p>
      <table border="0" bgcolor="#E0E0E0" width="100%">
        <tr>
          <td>
<pre class="PROGRAMLISTING">
&#13;GtkType
gtk_button_get_type (void)
{
  static GtkType button_type = 0;

  if (!button_type)
    {
      static const GtkTypeInfo button_info =
      {
        "GtkButton",
        sizeof (GtkButton),
        sizeof (GtkButtonClass),
        (GtkClassInitFunc) gtk_button_class_init,
        (GtkObjectInitFunc) gtk_button_init,
        /* reserved_1 */ NULL,
        /* reserved_2 */ NULL,
        (GtkClassInitFunc) NULL,
      };

      button_type = gtk_type_unique (GTK_TYPE_BIN, &amp;button_info);
      gtk_type_set_chunk_alloc (button_type, 16);
    }

  return button_type;
}
&#13;
</pre>
          </td>
        </tr>
      </table>
      <p>
        The code fills in a struct with information about the
        class, then hands that struct to GTK+ to get a type
        identifier (<span class="STRUCTNAME">GtkType</span>). Only
        six components of the <span class="STRUCTNAME">
        GtkTypeInfo</span> struct are important. <tt class= 
        "CLASSNAME">GtkButton</tt> gives GTK+ a human-readable name
        for the class, used in error messages and the like; the
        size of the instance and class structs; then a function to
        initialize the class struct and another to initialize each
        new instance. The sixth and seventh members of the struct
        (<span class="STRUCTNAME">reserved_1</span> and <span
        class="STRUCTNAME">reserved_2</span>) are obsolete and
        preserved only for compatibility. The final member is a
        pointer to a base class initialization function, used to
        initialize the class struct of any subclasses.
      </p>
      <p>
        <tt class="FUNCTION">gtk_type_unique()</tt> registers the
        new type and obtains a type identifier. The <span class= 
        "STRUCTNAME">GTK_TYPE_BIN</span> argument is a macro
        containing the type of <tt class="CLASSNAME">
        GtkButton</tt>'s parent class, <tt class="CLASSNAME">
        GtkBin</tt>. The call to <tt class="FUNCTION">
        gtk_type_set_chunk_alloc()</tt> optimizes memory allocation
        for this type; it is never required, and should only be
        used for frequently-allocated types like <tt class= 
        "CLASSNAME">GtkButton</tt>.
      </p>
      <p>
        Given a registered <tt class="CLASSNAME">GtkButton</tt>
        type, the following code creates a type instance:
      </p>
      <table border="0" bgcolor="#E0E0E0" width="100%">
        <tr>
          <td>
<pre class="PROGRAMLISTING">
&#13;GtkWidget*
gtk_button_new (void)
{
  return GTK_WIDGET (gtk_type_new (gtk_button_get_type ()));
}
&#13;
</pre>
          </td>
        </tr>
      </table>
      <p>
        The newborn <tt class="CLASSNAME">GtkButton</tt> will be
        initialized by its instance initializer. The instance
        initialization function is called each time an instance of
        the type is created; it gives the object's data members
        reasonable default values:
      </p>
      <table border="0" bgcolor="#E0E0E0" width="100%">
        <tr>
          <td>
<pre class="PROGRAMLISTING">
&#13;static void
gtk_button_init (GtkButton *button)
{
  GTK_WIDGET_SET_FLAGS (button, GTK_CAN_FOCUS);
  GTK_WIDGET_UNSET_FLAGS (button, GTK_NO_WINDOW);

  button-&gt;child = NULL;
  button-&gt;in_button = FALSE;
  button-&gt;button_down = FALSE;
  button-&gt;relief = GTK_RELIEF_NORMAL;
}
&#13;
</pre>
          </td>
        </tr>
      </table>
      <p>
        Remember that <tt class="FUNCTION">gtk_button_init()</tt>
        was passed to <tt class="FUNCTION">gtk_type_unique()</tt>
        when the <tt class="CLASSNAME">GtkButton</tt> type was
        created. GTK+ stores the function pointer and uses it to
        create <tt class="CLASSNAME">GtkButton</tt> instances.
      </p>
      <p>
        Instance structs are created with all bits set to 0; so
        settings members to 0 or <span class="STRUCTNAME">
        NULL</span> is not strictly necessary. Still, most GTK+
        code does initialize the members, for clarity.
      </p>
      <p>
        The class initialization and base class initialization
        functions require some background information to understand
        fully; you will know how to write them after you read this
        chapter.
      </p>
    </div>
    <div class="NAVFOOTER">
      <br>
      <br>
      <table width="100%" border="0" bgcolor="#ffffff" cellpadding= 
      "1" cellspacing="0">
        <tr>
          <td width="25%" bgcolor="#ffffff" align="left">
            <a href="cha-objects.html"><font color="#0000ff" size=
            "2"><b>&lt;&lt;&lt; Previous</b></font></a>
          </td>
          <td width="25%" colspan="2" bgcolor="#ffffff" align= 
          "center">
            <font color="#0000ff" size="2"><b><a href="ggad.html">
            <font color="#0000ff" size="2"><b>
            Home</b></font></a></b></font>
          </td>
          <td width="25%" bgcolor="#ffffff" align="right">
            <a href="sec-classinit.html"><font color="#0000ff"
            size="2"><b>Next &gt;&gt;&gt;</b></font></a>
          </td>
        </tr>
        <tr>
          <td colspan="2" align="left">
            <font color="#000000" size="2"><b>The GTK+ Object and
            Type System</b></font>
          </td>
          <td colspan="2" align="right">
            <font color="#000000" size="2"><b>Initializing a New
            Class</b></font>
          </td>
        </tr>
      </table>
    </div>
  </body>
</html>