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;
}