Gobject的对象方法

Posted luizp

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Gobject的对象方法相关的知识,希望对你有一定的参考价值。

Gobject的对象方法有如下几种:

1、非虚拟公共方法
2、虚拟公共方法
3、虚拟私有方法


1、非虚拟公共方法

这个是最简单的,提供了一种作用于对象的简单方法。 在头文件中提供函数原型,并在源文件中提供该原型的实现。

/* declaration in the header. */
void viewer_file_open (ViewerFile  *self,
                       GError     **error);

/* implementation in the source file */
void
viewer_file_open (ViewerFile  *self,
                  GError     **error)
{
  g_return_if_fail (VIEWER_IS_FILE (self));
  g_return_if_fail (error == NULL || *error == NULL);

  /* do stuff here. */
}

2、虚拟公共方法

这是创建GObject的可覆盖函数的首选:
(1)在公共头文件中的类结构中定义通用方法及其虚函数
(2)在头文件中定义通用方法,并在源文件中实现它
(3)在源文件中实现虚拟函数的基本版本,并在对象的class_init函数中初始化该实现的虚函数指针; 或者将其赋值为NULL的纯虚拟函数,该函数必须由派生类覆盖。
(4)在需要覆盖它的每个派生类中重新实现虚拟函数
请注意,虚拟函数只能在类可派生时定义,使用G_DECLARE_DERIVABLE_TYPE声明,因此可以定义类结构。

/* declaration in viewer-file.h. */
#define VIEWER_TYPE_FILE viewer_file_get_type ()
G_DECLARE_DERIVABLE_TYPE (ViewerFile, viewer_file, VIEWER, FILE, GObject)

struct _ViewerFileClass
{
  GObjectClass parent_class;

  /* stuff */
  void (*open) (ViewerFile  *self,
                GError     **error);

  /* Padding to allow adding up to 12 new virtual functions without
   * breaking ABI. */
  gpointer padding[12];
};

void viewer_file_open (ViewerFile  *self,
                       GError     **error);

/* implementation in viewer-file.c */
void
viewer_file_open (ViewerFile  *self,
                  GError     **error)
{
  ViewerFileClass *klass;

  g_return_if_fail (VIEWER_IS_FILE (self));
  g_return_if_fail (error == NULL || *error == NULL);

  klass = VIEWER_FILE_GET_CLASS (self);
  g_return_if_fail (klass->open != NULL);

  klass->open (self, error);
}

上面的代码简单地将打开的调用重定向到相关的虚拟函数。
可以在对象的class_init函数中为此类方法提供默认实现:将klass->open字段初始化为指向实际实现的指针。 默认情况下,不被继承的类方法被初始化为NULL,因此被认为是“纯虚拟”。

static void
viewer_file_real_close (ViewerFile  *self,
                        GError     **error)
{
  /* Default implementation for the virtual method. */
}

static void
viewer_file_class_init (ViewerFileClass *klass)
{
  /* this is not necessary, except for demonstration purposes.
   *
   * pure virtual method: mandates implementation in children.
   */
  klass->open = NULL;

  /* merely virtual method. */
  klass->close = viewer_file_real_close;
}

void
viewer_file_open (ViewerFile  *self,
                  GError     **error)
{
  ViewerFileClass *klass;

  g_return_if_fail (VIEWER_IS_FILE (self));
  g_return_if_fail (error == NULL || *error == NULL);

  klass = VIEWER_FILE_GET_CLASS (self);

  /* if the method is purely virtual, then it is a good idea to
   * check that it has been overridden before calling it, and,
   * depending on the intent of the class, either ignore it silently
   * or warn the user.
   */
  g_return_if_fail (klass->open != NULL);
  klass->open (self, error);
}

void
viewer_file_close (ViewerFile  *self,
                   GError     **error)
{
  ViewerFileClass *klass;

  g_return_if_fail (VIEWER_IS_FILE (self));
  g_return_if_fail (error == NULL || *error == NULL);

  klass = VIEWER_FILE_GET_CLASS (self);
  if (klass->close != NULL)
    klass->close (self, error);
}

(3)虚拟私有方法
这些与虚拟公共方法非常相似。他们只是没有直接调用公共函数。头文件仅包含虚函数的声明:

/* declaration in viewer-file.h. */
struct _ViewerFileClass
{
  GObjectClass parent;

  /* Public virtual method as before. */
  void     (*open)           (ViewerFile  *self,
                              GError     **error);

  /* Private helper function to work out whether the file can be loaded via
   * memory mapped I/O, or whether it has to be read as a stream. */
  gboolean (*can_memory_map) (ViewerFile *self);

  /* Padding to allow adding up to 12 new virtual functions without
   * breaking ABI. */
  gpointer padding[12];
};

void viewer_file_open (ViewerFile *self, GError **error);

这些虚拟函数通常用于将部分功能委托给子类实现:

/* this accessor function is static: it is not exported outside of this file. */
static gboolean 
viewer_file_can_memory_map (ViewerFile *self)
{
  return VIEWER_FILE_GET_CLASS (self)->can_memory_map (self);
}

void
viewer_file_open (ViewerFile  *self,
                  GError     **error)
{
  g_return_if_fail (VIEWER_IS_FILE (self));
  g_return_if_fail (error == NULL || *error == NULL);

  /*
   * Try to load the file using memory mapped I/O, if the implementation of the
   * class determines that is possible using its private virtual method.
   */
  if (viewer_file_can_memory_map (self))
    {
      /* Load the file using memory mapped I/O. */
    }
  else
    {
      /* Fall back to trying to load the file using streaming I/O… */
    }
}

同样,可能会为这个虚拟私有函数提供一个默认的实现。

static gboolean
viewer_file_real_can_memory_map (ViewerFile *self)
{
  /* As an example, always return false. Or, potentially return true if the
   * file is local. */
  return FALSE;
}

static void
viewer_file_class_init (ViewerFileClass *klass)
{
  /* non-pure virtual method; does not have to be implemented in children. */
  klass->can_memory_map = viewer_file_real_can_memory_map;
}

派生类可以用如下代码覆盖该方法:

static void
viewer_audio_file_class_init (ViewerAudioFileClass *klass)
{
  ViewerFileClass *file_class = VIEWER_FILE_CLASS (klass);

  /* implement pure virtual function. */
  file_class->can_memory_map = viewer_audio_file_can_memory_map;
}

 

以上是关于Gobject的对象方法的主要内容,如果未能解决你的问题,请参考以下文章

如何在python中正确关闭gobject主循环?

Gobject 的函数 G_TYPE_INSTANCE_GET_PRIVATE 已弃用

为啥即使回调参数与 XML 中的参数不匹配,GObject 方法仍会被调用?

GLib 和 GObject 到底是啥?

如何停止 dbus gobject 循环

GLib-GObject-WARNING **: Two different plugins tried to register