?? z105.html
字號:
<!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><<< 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 >>></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"> GtkType gtk_button_get_type(); </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"> #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)) </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"> g_return_if_fail(GTK_IS_BUTTON(widget)); </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"> GtkTypegtk_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, &button_info); gtk_type_set_chunk_alloc (button_type, 16); } return button_type;} </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"> GtkWidget*gtk_button_new (void){ return GTK_WIDGET (gtk_type_new (gtk_button_get_type ()));} </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"> static voidgtk_button_init (GtkButton *button){ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_FOCUS); GTK_WIDGET_UNSET_FLAGS (button, GTK_NO_WINDOW); button->child = NULL; button->in_button = FALSE; button->button_down = FALSE; button->relief = GTK_RELIEF_NORMAL;} </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><<< 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 >>></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>
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -