使用C语言进行面向对象的开发--GObject入门[4]

本文详细介绍了如何使用GObject框架创建一个名为JcBoy的类,包括实例结构和类结构的初始化过程,以及如何通过宏定义简化类的注册流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Part 4

   接上文.
前面定义了几个结构,我们可以把那些东西放在一个jc_boy.h文件中,下面开始介绍如何去实现这个BOY类,也就是要放在jc_boy.c中的部分。
对于GObject而言,有了实例结构,有了类结构,自然要有如何初始化的函数,毕竟这是C语言吗,没有那么方便的事儿。

相应的,对应于jc_boy,要定义jc_boy_init和jc_boy_class_init两个函数,当然他们分别对应于实例结构和类结构的初始化。

static void
jc_boy_init (JcBoy *self)
{
     JcBoyPrivate *priv=NULL;
     pri=self->private = JC_BOY_GET_PRIVATE (self); 
     priv->name=g_strdup("no-name");
     priv->hobby=g_strdup("nothing");
     priv->age=0;
}

 

static用于声明作用域,对于由多个文件构成的工程而言,很有必要。

       看到JC_BOY_GET_PRIVATE了吧,就是前面的那个宏定义,它调用的是G_TYPE_INSTANCE_GET_PRIVATE,一看全都是大写和下划线,
直觉告诉我们这还是宏定义,没错,它调用的是g_type_instance_get_private。 有时感觉这么折腾几下会很麻烦,但GObject就是建议大家
这么用,如果你不想使用那么一堆宏定义,那么直接使用g_type_instance_get_private之类的函数也是可以的。
JC_BOY_GET_PRIVATE获取了一个指向实例私有结构体的一个指针,接下来就是对其初始化了,注意g_strdup在堆上分配了一个字符串,
在后面介绍的类的析构的时候,我们应该将其free一下。 
P.S.你可以把这里的init理解为construtor,也可以不这样理解,因为GObject的类中提供了construtor函数,你可以在你定义的类中重写它。
但是一般简单的应用直接在初始化函数中处理了。
下面再看下类结构的初始化
static void
jc_boy_class_init (JcBoyClass *klass)

{
    g_type_class_add_private (klass, sizeof (JcBoyPrivate));
    klass->play=play;
}
首先将实例中的私有结构在类结构中声明下,这里用的是g_type_class_add_private.这里就没有使用宏定义。
然后将类结构中的那个函数指向一个函数,
void play()
{
    g_print(“the boy is playing football !/n”);
}
但有结构的初始化函数,还需要向GObject系统注册这个类【就是注册有这么一个类型】。
类的注册其实是比较麻烦的,这要用到g_type_register_***,可以注册成fundamental的,static的,dynamic的,
一般的应用基本用的都是static的,也是本文要讲述的【主要是自己还没怎么研究dynamic的缘故……XD】
以g_type_register_static为例
GType   g_type_register_static(GType parent_type,
                                                      const gchar *type_name,
                                                      const GTypeInfo *info,
                                                      GTypeFlags flags);
看英文大概能明白每个参数是干嘛的,这里面比较麻烦的是GTypeInfo,还是简单看下
typedef struct {
  /* interface types, classed types, instantiated types */
  guint16                class_size;
  
  GBaseInitFunc          base_init;
  GBaseFinalizeFunc      base_finalize;
  
  /* interface types, classed types, instantiated types */
  GClassInitFunc         class_init;
  GClassFinalizeFunc     class_finalize;
  gconstpointer          class_data;
  
  /* instantiated types */
  guint16                instance_size;
  guint16                n_preallocs;
  GInstanceInitFunc      instance_init;
  
  /* value handling */
  const GTypeValueTable    *value_table;
} GTypeInfo;

不要多看,多看会更头晕,但这并不影响我们使用GObject来构建对象

【什么?你非要弄明白?那别看本文了,本文标题写着入门俩字呢!。。。。。。其实主要原因是自己也没有完全研究透。。。。。。XD】

 但是要明白这里向系统声明了init ,finalize等等函式。

 为了简化这些步骤,GObject里面为我们提供了一些简化宏定义。

 这里介绍一个比较简单的 G_DEFINE_TYPE (JcBoy , jc_boy , G_TYPE_OBJECT) ;

前两个函式主要用于宏展开,最后一个用于表明父类的类型【对于继承下来的类,最后一个参数可别用错】

 还是展开看一下,其实还是比较麻烦的,具体我就不多说了。
#define G_DEFINE_TYPE(TN, t_n, T_P) G_DEFINE_TYPE_EXTENDED (TN, t_n, T_P, 0, {})

#define G_DEFINE_TYPE_EXTENDED(TN, t_n, T_P, _f_, _C_)      _G_DEFINE_TYPE_EXTENDED_BEGIN (TN, t_n, T_P, _f_) {_C_;} _G_DEFINE_TYPE_EXTENDED_END()

#define _G_DEFINE_TYPE_EXTENDED_BEGIN(TypeName, type_name, TYPE_PARENT, flags) 

static void     type_name##_init              (TypeName        *self); /
static void     type_name##_class_init        (TypeName##Class *klass); /
static gpointer type_name##_parent_class = NULL; /
static void     type_name##_class_intern_init (gpointer klass) /
{ /
  type_name##_parent_class = g_type_class_peek_parent (klass); /
  type_name##_class_init ((TypeName##Class*) klass); /
} /
/
gulong/
type_name##_get_type (void) /
{ /
  static volatile gsize g_define_type_id__volatile = 0; /
  if (g_once_init_enter (&g_define_type_id__volatile))  /
    { /
      gulongg_define_type_id = /
        g_type_register_static_simple (TYPE_PARENT, /
                                       g_intern_static_string (#TypeName), /
                                       sizeof (TypeName##Class), /
                                       (GClassInitFunc) type_name##_class_intern_init, /
                                       sizeof (TypeName), /
                                       (GInstanceInitFunc) type_name##_init, /
                                       (GTypeFlags) flags); /
      { /* custom code follows */
#define _G_DEFINE_TYPE_EXTENDED_END()   /
        /* following custom code */ /
      }                 /
      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); /
    }                   /
  return g_define_type_id__volatile;    /
} /* closes type_name##_get_type() */
另外,为了方便设置类中的成员还要设置几个可以由外部调用的的函数。
void jc_boy_change_hobby(JcBoy *self,gchar *hobby)
{
    JcBoyPrivate *priv;
    self->priv = priv = JC_BOY_GET_PRIVATE(self);
    g_free (priv->hobby);
    priv->hobby=g_strdup("playing basketball");
    g_print("recently the boy is interested in %s/n",hobby);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值