sec6-可派生类型和抽象类型
创始人
2024-05-04 08:25:31
0

可派生类型

有两种类型,final类型和derivable类型。final类型没有任何子对象。derivable有子对象。

这两个对象之间的主要区别是它们的类。final类型对象没有自己的类区域。类的唯一成员是它的父类。

派生对象在类中有自己的区域。该类对其子类开放。

G_DECLARE_DERIVABLE_TYPE 用于声明可派生类型。它像这样写在头文件中:

#define T_TYPE_NUMBER             (t_number_get_type ())
G_DECLARE_DERIVABLE_TYPE (TNumber, t_number, T, NUMBER, GObject)

抽象类

抽象类型没有任何实例。这种类型的对象是可衍生的,它的子对象可以使用抽象对象的函数和信号。

本节的例子是TNumber, TInt和TDouble对象。TInt和TDouble已经在前一节中创建。它们分别代表整数和浮点数。数字比整数和浮点数更抽象。

TNumber是一个表示数字的抽象对象。TNumber是TInt和TDouble的父对象。TNumber没有被实例化,因为它的类型是抽象的。当一个实例具有TInt或TDouble类型时,它也是TNumber的实例。

TInt和TDouble有五种运算:加、减、乘、除和一元减运算。这些操作可以在TNumber对象上定义。

在本节中,我们将定义TNumber对象和上面的五个函数。此外,还将添加to_s函数。它将TNumber的值转换为字符串。它类似于sprintf函数。我们将重写TInt和TDouble来实现这些函数。

TNumber对象

/* filename: tnumber.h */1 #ifndef __T_NUMBER_H__2 #define __T_NUMBER_H__3 4 #include 5 6 #define T_TYPE_NUMBER             (t_number_get_type ())7 G_DECLARE_DERIVABLE_TYPE (TNumber, t_number, T, NUMBER, GObject)8 9 struct _TNumberClass {
10   GObjectClass parent_class;
11   TNumber* (*add) (TNumber *self, TNumber *other);
12   TNumber* (*sub) (TNumber *self, TNumber *other);
13   TNumber* (*mul) (TNumber *self, TNumber *other);
14   TNumber* (*div) (TNumber *self, TNumber *other);
15   TNumber* (*uminus) (TNumber *self);
16   char * (*to_s) (TNumber *self);
17   /* signal */
18   void (*div_by_zero) (TNumber *self);
19 };
20 
21 /* arithmetic operator */
22 /* These operators create a new instance and return a pointer to it. */
23 TNumber *
24 t_number_add (TNumber *self, TNumber *other);
25 
26 TNumber *
27 t_number_sub (TNumber *self, TNumber *other);
28 
29 TNumber *
30 t_number_mul (TNumber *self, TNumber *other);
31 
32 TNumber *
33 t_number_div (TNumber *self, TNumber *other);
34 
35 TNumber *
36 t_number_uminus (TNumber *self);
37 
38 char *
39 t_number_to_s (TNumber *self);
40 #endif /* __T_NUMBER_H__ */
41 
  • 7: G_DECLARE_DERIVABLE_TYPE宏。这类似于G_DECLARE_FINAL_TYPE宏。不同之处是可派生的类或最终的类。G_DECLARE_DERIVABLE_TYPE展开为:

    1.t_number_get_type()函数的声明。该函数必须在tnumber.c文件中定义。定义通常使用G_DEFINE_TYPE或其家族宏完成。
    2.定义TNumber实例,其成员仅为其父实例。
    3.声明TNumberClass。它应该稍后在头文件中定义。
    4.定义了方便宏T_NUMBER(转换为实例),T_NUMBER_CLASS(转换为类),T_IS_NUMBER(实例检查),T_IS_NUMBER_CLASS(类检查)和T_NUMBER_GET_CLASS。
    5.g_autoptr()的支持。

  • 9-19: TNumberClass结构体的定义。
  • 11-16:定义了一些函数指针。它们被称为类方法或虚函数。它们将被后代对象中的函数重写。方法是5个算术运算符和to_s函数。To_s函数类似于sprintf函数。
  • 18:指向"div-by- 0 "信号的默认信号处理程序的指针。该指针的偏移量作为参数赋给g_signal_new。
  • 21-40:函数。它们是公有的。
/* filename: tnumber.c */1 #include "tnumber.h"2 3 static guint t_number_signal;4 5 G_DEFINE_ABSTRACT_TYPE (TNumber, t_number, G_TYPE_OBJECT)6 7 static void8 div_by_zero_default_cb (TNumber *self) {9   g_printerr ("\nError: division by zero.\n\n");
10 }
11 
12 static void
13 t_number_class_init (TNumberClass *class) {
14 
15   /* virtual functions */
16   class->add = NULL;
17   class->sub = NULL;
18   class->mul = NULL;
19   class->div = NULL;
20   class->uminus = NULL;
21   class->to_s = NULL;
22   /* default signal handler */
23   class->div_by_zero = div_by_zero_default_cb;
24   /* signal */
25   t_number_signal =
26   g_signal_new ("div-by-zero",
27                 G_TYPE_FROM_CLASS (class),
28                 G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
29                 G_STRUCT_OFFSET (TNumberClass, div_by_zero),
30                 NULL /* accumulator */,
31                 NULL /* accumulator data */,
32                 NULL /* C marshaller */,
33                 G_TYPE_NONE /* return_type */,
34                 0     /* n_params */
35                 );
36 }
37 
38 static void
39 t_number_init (TNumber *inst) {
40 }
41 
42 TNumber *
43 t_number_add (TNumber *self, TNumber *other) {
44   g_return_val_if_fail (T_IS_NUMBER (self), NULL);
45   g_return_val_if_fail (T_IS_NUMBER (other), NULL);
46 
47   TNumberClass *class = T_NUMBER_GET_CLASS(self);
48   return class->add ? class->add (self, other) : NULL;
49 }
50 
51 TNumber *
52 t_number_sub (TNumber *self, TNumber *other) {
53   g_return_val_if_fail (T_IS_NUMBER (self), NULL);
54   g_return_val_if_fail (T_IS_NUMBER (other), NULL);
55 
56   TNumberClass *class = T_NUMBER_GET_CLASS(self);
57   return class->sub ? class->sub (self, other) : NULL;
58 }
59 
60 TNumber *
61 t_number_mul (TNumber *self, TNumber *other) {
62   g_return_val_if_fail (T_IS_NUMBER (self), NULL);
63   g_return_val_if_fail (T_IS_NUMBER (other), NULL);
64 
65   TNumberClass *class = T_NUMBER_GET_CLASS(self);
66   return class->mul ? class->mul (self, other) : NULL;
67 }
68 
69 TNumber *
70 t_number_div (TNumber *self, TNumber *other) {
71   g_return_val_if_fail (T_IS_NUMBER (self), NULL);
72   g_return_val_if_fail (T_IS_NUMBER (other), NULL);
73 
74   TNumberClass *class = T_NUMBER_GET_CLASS(self);
75   return class->div ? class->div (self, other) : NULL;
76 }
77 
78 TNumber *
79 t_number_uminus (TNumber *self) {
80   g_return_val_if_fail (T_IS_NUMBER (self), NULL);
81 
82   TNumberClass *class = T_NUMBER_GET_CLASS(self);
83   return class->uminus ? class->uminus (self) : NULL;
84 }
85 
86 char *
87 t_number_to_s (TNumber *self) {
88   g_return_val_if_fail (T_IS_NUMBER (self), NULL);
89 
90   TNumberClass *class = T_NUMBER_GET_CLASS(self);
91   return class->to_s ? class->to_s (self) : NULL;
92 }
93 
  • 5: G_DEFINE_ABSTRACT_TYPE宏。此宏用于定义一个抽象类型对象。抽象类型没有实例化。这个宏被扩展为:
       1.t_number_init()函数的声明。
       2.t_number_class_init()函数的声明。
       3.定义t_number_get_type()函数。
       4.指向父类的静态变量t_number_parent_class的定义。
  • 3,7 - 10,25 -35:定义除零信号。Div_by_zero_default_cb是“div-by- 0”信号的默认处理程序。默认处理程序没有用户数据参数。使用g_signal_new代替g_signal_new_class_handler。g_signal_new指定一个处理程序(通过类指针偏移量)。
  • 12-36: t_number_class_init。
  • 16-21:这些类方法是虚函数。它们被期望在TNumber的后代对象中被覆盖。这里赋值为NULL,以便在调用方法时不发生任何事情。
  • 23:将函数dev_by_zero_default_cb的地址分配给class->div_by_zero。这是“div-by- 0”信号的默认处理程序。
  • 38-40: t_number_init是实例的初始化函数。但是抽象对象没有被实例化。在这个函数中什么都没有做。但是你不能忽略这个函数的定义。
  • 42-92:公有函数。如果指向类方法的指针不是NULL,这些函数只调用相应的类方法。

TInt object

tint.h是TInt对象的头文件。TInt是TNumber的子对象。

 1 #ifndef __T_INT_H__2 #define __T_INT_H__3 4 #include 5 #include "tnumber.h"6 7 #define T_TYPE_INT  (t_int_get_type ())8 G_DECLARE_FINAL_TYPE (TInt, t_int, T, INT, TNumber)9 
10 /* create a new TInt instance */
11 TInt *
12 t_int_new_with_value (int value);
13 
14 TInt *
15 t_int_new (void);
16 #endif /* __T_INT_H__ */
17 
  • 10-16:声明公有函数。算术函数和to_s是在TNumber中声明的,所以TInt不会声明这些函数。只声明实例创建函数。

tint.c实现了虚函数(类方法)。TNumberClass中方法的指针在这里被重写。

/* filename:tint.c  */1 #include "tint.h"2 #include "tdouble.h"3 4 #define PROP_INT 15 static GParamSpec *int_property = NULL;6 7 struct _TInt {8   TNumber parent;9   int value;10 };11 12 G_DEFINE_TYPE (TInt, t_int, T_TYPE_NUMBER)13 14 static void15 t_int_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) {16   TInt *self = T_INT (object);17 18   if (property_id == PROP_INT) {19     self->value = g_value_get_int (value);20   } else21     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);22 }23 24 static void25 t_int_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) {26   TInt *self = T_INT (object);27 28   if (property_id == PROP_INT)29     g_value_set_int (value, self->value);30   else31     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);32 }33 34 static void35 t_int_init (TInt *d) {36 }37 38 /* arithmetic operator */39 /* These operators create a new instance and return a pointer to it. */40 #define t_int_binary_op(op) \41   int i; \42   double d; \43   if (T_IS_INT (other)) { \44     g_object_get (T_INT (other), "value", &i, NULL); \45     return  T_NUMBER (t_int_new_with_value (T_INT(self)->value op i)); \46   } else { \47     g_object_get (T_DOUBLE (other), "value", &d, NULL); \48     return  T_NUMBER (t_int_new_with_value (T_INT(self)->value op (int) d)); \49   }50 51 static TNumber *52 t_int_add (TNumber *self, TNumber *other) {53   g_return_val_if_fail (T_IS_INT (self), NULL);54 55   t_int_binary_op (+)56 }57 58 static TNumber *59 t_int_sub (TNumber *self, TNumber *other) {60   g_return_val_if_fail (T_IS_INT (self), NULL);61 62   t_int_binary_op (-)63 }64 65 static TNumber *66 t_int_mul (TNumber *self, TNumber *other) {67   g_return_val_if_fail (T_IS_INT (self), NULL);68 69   t_int_binary_op (*)70 }71 72 static TNumber *73 t_int_div (TNumber *self, TNumber *other) {74   g_return_val_if_fail (T_IS_INT (self), NULL);75   int i;76   double d;77 78   if (T_IS_INT (other)) {79     g_object_get (T_INT (other), "value", &i, NULL);80     if (i == 0) {81       g_signal_emit_by_name (self, "div-by-zero");82       return NULL;83     } else84       return  T_NUMBER (t_int_new_with_value (T_INT(self)->value / i));85   } else {86     g_object_get (T_DOUBLE (other), "value", &d, NULL);87     if (d == 0) {88       g_signal_emit_by_name (self, "div-by-zero");89       return NULL;90     } else91       return  T_NUMBER (t_int_new_with_value (T_INT(self)->value / (int)  d));92   }93 }94 95 static TNumber *96 t_int_uminus (TNumber *self) {97   g_return_val_if_fail (T_IS_INT (self), NULL);98 99   return T_NUMBER (t_int_new_with_value (- T_INT(self)->value));
100 }
101 
102 static char *
103 t_int_to_s (TNumber *self) {
104   g_return_val_if_fail (T_IS_INT (self), NULL);
105   int i;
106 
107   g_object_get (T_INT (self), "value", &i, NULL); 
108   return g_strdup_printf ("%d", i);
109 }
110 
111 static void
112 t_int_class_init (TIntClass *class) {
113   TNumberClass *tnumber_class = T_NUMBER_CLASS (class);
114   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
115 
116   /* override virtual functions */
117   tnumber_class->add = t_int_add;
118   tnumber_class->sub = t_int_sub;
119   tnumber_class->mul = t_int_mul;
120   tnumber_class->div = t_int_div;
121   tnumber_class->uminus = t_int_uminus;
122   tnumber_class->to_s = t_int_to_s;
123 
124   gobject_class->set_property = t_int_set_property;
125   gobject_class->get_property = t_int_get_property;
126   int_property = g_param_spec_int ("value", "val", "Integer value", G_MININT, G_MAXINT, 0, G_PARAM_READWRITE);
127   g_object_class_install_property (gobject_class, PROP_INT, int_property);
128 }
129 
130 TInt *
131 t_int_new_with_value (int value) {
132   TInt *d;
133 
134   d = g_object_new (T_TYPE_INT, "value", value, NULL);
135   return d;
136 }
137 
138 TInt *
139 t_int_new (void) {
140   TInt *d;
141 
142   d = g_object_new (T_TYPE_INT, NULL);
143   return d;
144 }
145 
  • 4- 5,14 - 32,124 -127:属性“value”的定义。这和以前一样。
  • 7-10: TInt结构的定义。必须在G_DEFINE_TYPE之前定义。
  • 12: G_DEFINE_TYPE宏。这个宏展开为:
       1.t_int_init()函数的声明。
       2.t_int_get_type()函数的定义。
       3.定义指向父类的静态变量t_int_parent_class。
  • 34-36: t_int_init。
  • 40-109:这些函数连接到TIntClass中的类方法指针。它们是tnumber.c中定义的虚函数的实现。
  • 40-49:定义在t_int_add, t_int_sub和t_int_mul中使用的宏。这个宏类似于t_int_div函数。请参阅下面对t_int_div的解释。
  • 51-70: t_int_add, t_int_sub, t_int_mul函数。使用宏t_int_binary_op。
  • 72 - 93: t_int_div。Self是调用函数的对象。other是另一个TNumber对象。它可以是TInt或TDouble。如果是TDouble,则在执行除法之前将其值转换为int。如果除数(other)为零,则发出“div-by- 0”信号。信号在TNumber中定义,所以TInt不知道信号id。发射使用g_signal_emit_by_name而不是g_signal_emit完成。t_int_div的返回值是TNumber类型的对象。但是,因为TNumber是抽象的,所以该对象的实际类型是TInt。
  • 95-100:一元负运算符的函数。
  • 102-109: to_s函数。这个函数将int转换为字符串。例如,如果该对象的值为123,则结果为字符串“123”。如果字符串变得无用,调用者应该释放它。
  • 111—128:t_int_class_init。
  • 117-122:类方法被重写。例如,如果在TInt对象上调用t_number_add,则该函数调用类方法*tnumber_class->add。指针指向t_int_add函数。因此,最后调用t_int_add。
  • 130-144:实例创建功能不变。

TDouble object

TDoubleicloud对象由TDouble .h和TDouble .c定义。它的定义与TInt非常相似。因此,这个小节只显示文件的内容。

/* filename: tdouble.h */1 #ifndef __T_DOUBLE_H__2 #define __T_DOUBLE_H__3 4 #include 5 #include "tnumber.h"6 7 #define T_TYPE_DOUBLE  (t_double_get_type ())8 G_DECLARE_FINAL_TYPE (TDouble, t_double, T, DOUBLE, TNumber)9 
10 /* create a new TDouble instance */
11 TDouble *
12 t_double_new_with_value (double value);
13 
14 TDouble *
15 t_double_new (void);
16 #endif /* __T_DOUBLE_H__ */
17 
/* filename: tdouble.c */1 #include "tdouble.h"2 #include "tint.h"3 4 #define PROP_DOUBLE 15 static GParamSpec *double_property = NULL;6 7 struct _TDouble {8   TNumber parent;9   double value;10 };11 12 G_DEFINE_TYPE (TDouble, t_double, T_TYPE_NUMBER)13 14 static void15 t_double_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) {16   TDouble *self = T_DOUBLE (object);17   if (property_id == PROP_DOUBLE) {18     self->value = g_value_get_double (value);19   } else20     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);21 }22 23 static void24 t_double_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) {25   TDouble *self = T_DOUBLE (object);26 27   if (property_id == PROP_DOUBLE)28     g_value_set_double (value, self->value);29   else30     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);31 }32 33 static void34 t_double_init (TDouble *d) {35 }36 37 /* arithmetic operator */38 /* These operators create a new instance and return a pointer to it. */39 #define t_double_binary_op(op) \40   int i; \41   double d; \42   if (T_IS_INT (other)) { \43     g_object_get (T_INT (other), "value", &i, NULL); \44     return  T_NUMBER (t_double_new_with_value (T_DOUBLE(self)->value op (double) i)); \45   } else { \46     g_object_get (T_DOUBLE (other), "value", &d, NULL); \47     return  T_NUMBER (t_double_new_with_value (T_DOUBLE(self)->value op d)); \48   }49 50 static TNumber *51 t_double_add (TNumber *self, TNumber *other) {52   g_return_val_if_fail (T_IS_DOUBLE (self), NULL);53 54   t_double_binary_op (+)55 }56 57 static TNumber *58 t_double_sub (TNumber *self, TNumber *other) {59   g_return_val_if_fail (T_IS_DOUBLE (self), NULL);60 61   t_double_binary_op (-)62 }63 64 static TNumber *65 t_double_mul (TNumber *self, TNumber *other) {66   g_return_val_if_fail (T_IS_DOUBLE (self), NULL);67 68   t_double_binary_op (*)69 }70 71 static TNumber *72 t_double_div (TNumber *self, TNumber *other) {73   g_return_val_if_fail (T_IS_DOUBLE (self), NULL);74   int i;75   double d;76 77   if (T_IS_INT (other)) {78     g_object_get (T_INT (other), "value", &i, NULL);79     if (i == 0) {80       g_signal_emit_by_name (self, "div-by-zero");81       return NULL;82     } else83       return  T_NUMBER (t_double_new_with_value (T_DOUBLE(self)->value / (double) i));84   } else {85     g_object_get (T_DOUBLE (other), "value", &d, NULL);86     if (d == 0) {87       g_signal_emit_by_name (self, "div-by-zero");88       return NULL;89     } else90       return  T_NUMBER (t_double_new_with_value (T_DOUBLE(self)->value / d));91   }92 }93 94 static TNumber *95 t_double_uminus (TNumber *self) {96   g_return_val_if_fail (T_IS_DOUBLE (self), NULL);97 98   return T_NUMBER (t_double_new_with_value (- T_DOUBLE(self)->value));99 }
100 
101 static char *
102 t_double_to_s (TNumber *self) {
103   g_return_val_if_fail (T_IS_DOUBLE (self), NULL);
104   double d;
105 
106   g_object_get (T_DOUBLE (self), "value", &d, NULL);
107   return g_strdup_printf ("%lf", d);
108 }
109 
110 static void
111 t_double_class_init (TDoubleClass *class) {
112   TNumberClass *tnumber_class = T_NUMBER_CLASS (class);
113   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
114 
115   /* override virtual functions */
116   tnumber_class->add = t_double_add;
117   tnumber_class->sub = t_double_sub;
118   tnumber_class->mul = t_double_mul;
119   tnumber_class->div = t_double_div;
120   tnumber_class->uminus = t_double_uminus;
121   tnumber_class->to_s = t_double_to_s;
122 
123   gobject_class->set_property = t_double_set_property;
124   gobject_class->get_property = t_double_get_property;
125   double_property = g_param_spec_double ("value", "val", "Double value", -G_MAXDOUBLE, G_MAXDOUBLE, 0, G_PARAM_READWRITE);
126   g_object_class_install_property (gobject_class, PROP_DOUBLE, double_property);
127 }
128 
129 TDouble *
130 t_double_new_with_value (double value) {
131   TDouble *d;
132 
133   d = g_object_new (T_TYPE_DOUBLE, "value", value, NULL);
134   return d;
135 }
136 
137 TDouble *
138 t_double_new (void) {
139   TDouble *d;
140 
141   d = g_object_new (T_TYPE_DOUBLE, NULL);
142   return d;
143 }
144 
/* filename: mainc.c */1 #include 2 #include "tnumber.h"3 #include "tint.h"4 #include "tdouble.h"5 6 static void7 notify_cb (GObject *gobject, GParamSpec *pspec, gpointer user_data) {8   const char *name;9   int i;
10   double d;
11 
12   name = g_param_spec_get_name (pspec);
13   if (T_IS_INT (gobject) && strcmp (name, "value") == 0) {
14     g_object_get (T_INT (gobject), "value", &i, NULL);
15     g_print ("Property \"%s\" is set to %d.\n", name, i);
16   } else if (T_IS_DOUBLE (gobject) && strcmp (name, "value") == 0) {
17     g_object_get (T_DOUBLE (gobject), "value", &d, NULL);
18     g_print ("Property \"%s\" is set to %lf.\n", name, d);
19   }
20 }
21 
22 int
23 main (int argc, char **argv) {
24   TNumber *i, *d, *num;
25   char *si, *sd, *snum;
26 
27   i = T_NUMBER (t_int_new ());
28   d = T_NUMBER (t_double_new ());
29 
30   g_signal_connect (G_OBJECT (i), "notify::value", G_CALLBACK (notify_cb), NULL);
31   g_signal_connect (G_OBJECT (d), "notify::value", G_CALLBACK (notify_cb), NULL);
32 
33   g_object_set (T_INT (i), "value", 100, NULL);
34   g_object_set (T_DOUBLE (d), "value", 12.345, NULL);
35 
36   num = t_number_add (i, d);
37 
38   si = t_number_to_s (i);
39   sd = t_number_to_s (d);
40   snum = t_number_to_s (num);
41 
42   g_print ("%s + %s is %s.\n", si, sd, snum);
43 
44   g_object_unref (num);
45   g_free (snum);
46 
47   num = t_number_add (d, i);
48   snum = t_number_to_s (num);
49 
50   g_print ("%s + %s is %s.\n", sd, si, snum);
51 
52   g_object_unref (num);
53   g_free (sd);
54   g_free (snum);
55 
56   g_object_set (T_DOUBLE (d), "value", 0.0, NULL);
57   sd = t_number_to_s (d);
58   if ((num = t_number_div(i, d)) != NULL) {
59     snum = t_number_to_s (num);
60     g_print ("%s / %s is %s.\n", si, sd, snum);
61     g_object_unref (num);
62     g_free (snum);
63   }
64 
65   g_object_unref (i);
66   g_object_unref (d);
67   g_free (si);
68   g_free (sd);
69 
70   return 0;
71 }
72 
  • 6-20:“notify”处理程序。这个处理程序已经升级,可以同时支持TInt和TDouble。
    22-71:函数main。
    30-31:连接i (TInt)和d (TDouble)上的notify信号。
    33-34:设置i和d的value属性
    36: i加d。答案是TInt对象。
    47:将i加到d。答案是TDouble对象。两个TNumber对象的加法不是可交换的,因为交换后的结果类型不同。
    56-63:测试除零信号。

类初始化过程

  1. GObjectClass在main函数之前已经被初始化(这个和GCC编译器有关,GCC编译器已经给初始化)
  2. 第一次调用g_object_new (T_TYPE_INT,…)或g_object_new (T_TYPE_DOUBLE,…)初始化TNumberClass。因为TNumber是一个抽象对象,所以不能实例化它。相反,它的子对象TInt或TDouble可以被实例化。当子类第一次被实例化时,TNumberClass会在子类初始化之前被初始化。初始化过程如下。
  3. 给TNumberClass类分配内存。
  4. 拷贝父类部分(GObjectClass)。
  5. t_number_class_init被调用去初始化TNumberClass。这包括初始化指向类方法处理程序的指针和默认信号处理程序。

下图显示了这个过程。
在这里插入图片描述

TIntClass的初始化过程

  1. GNumberClass在开始初始化GIntClass之前已经初始化。
  2. 第一次调用g_object_new (T_TYPE_INT,…)初始化TIntClass。初始化过程如下。
  3. 内存被分配给TIntClass。TIntClass没有自己的区域。因此,它的结构与其父类(TNumberClass)相同。
  4. 类的父类(TNumberClass)部分(这与整个TIntClass相同)是从TNumberClass复制的。
  5. 调用t_int_class_init来初始化TIntClass。这包括重写类方法set_property和get_property。

下图显示了这个过程。
在这里插入图片描述
翻译自:GObject tutorial

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
客厅放八骏马摆件可以吗(家里摆... 今天给各位分享客厅放八骏马摆件可以吗的知识,其中也会对家里摆八骏马摆件好吗进行解释,如果能碰巧解决你...
苏州离哪个飞机场近(苏州离哪个... 本篇文章极速百科小编给大家谈谈苏州离哪个飞机场近,以及苏州离哪个飞机场近点对应的知识点,希望对各位有...