3.派生类和抽象类

这篇具有很好参考价值的文章主要介绍了3.派生类和抽象类。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

参考资料:https://github.com/ToshioCP/Gobject-tutorial/blob/main/gfm/sec6.md

抽象类型没有任何实例。

G_DECLARE_DERIVABLE_TYPE宏用来声明抽象类。这类似于G_DECLARE_FINAL_TYPE宏。

比如面的例子,MNuber是抽象类,G_DECLARE_DERIVABLE_TYPE扩展为:

  1. 函数声明m_number_get_type(),你需要定义它。你可以用G_DEFINE_TYPE等宏定义它。
  2. MNumber实例的定义,它的成员仅仅有它的父类。
  3. MNumberClass的声明。你需要在头文件后面定义它。
  4. M_NUMBER (cast to instance) 、M_NUMBER_CLASS (cast to class) 、M_IS_NUMBER (instance check)、M_IS_MUBER_CLASS (class check)、M_NUMBER_GET_CLASS宏。
  5. 提供g_autoptr()

然后,是定义MNumberClass结构退。

下来,是初始化函数指针,它们被称为类方法或虚函数。子类对象需要覆盖它们。

然后是一些公开的函数。

1. 抽象类MNumber

m_number.h:

#ifndef M_NUMBER_H
#define M_NUMBER_H

#include <glib-object.h>

#define M_TYPE_NUMBER   (m_number_get_type())
G_DECLARE_DERIVABLE_TYPE (MNumber, m_number, M, NUMBER, GObject)

struct _MNumberClass {
	GObjectClass base_class;
	MNumber * (*add) (MNumber *self, MNumber *other);
	MNumber * (*sub) (MNumber *self, MNumber *other);
	MNumber * (*mul) (MNumber *self, MNumber *other);
	MNumber * (*div) (MNumber *self, MNumber *other);
	MNumber * (*uminus) (MNumber *self);
	
	char * (*to_str) (MNumber *self);
};

MNumber *
m_number_add (MNumber *self, MNumber *other);

MNumber *
m_number_sub (MNumber *self, MNumber *other);

MNumber *
m_number_mul (MNumber *self, MNumber *other);

MNumber *
m_number_div (MNumber *self, MNumber *other);

MNumber *
m_number_uminus (MNumber *self);

char *
m_number_to_str (MNumber *self);


#endif // M_NUMBER_H

下面的,G_DEFINE_ABSTRACT_TYPE宏,用于定义抽象类型对象。抽象类型不能被实例化。
这个宏扩展为:

  1. m_number_init()函数声明。
  2. m_number_class_init()函数声明。
  3. m_number_get_tyoe()函数定义
  4. m_number_parent_class静态变量的定义,它指向父类。

虚函数指针分配为NULL,需要让后代覆盖。

m_number_init()是实例初始化函数,但是抽象对象不被实例化,所以它什么都不做。但是不能省略这个函数定义。

m_number.c:

#include "m_number.h"

G_DEFINE_ABSTRACT_TYPE (MNumber, m_number, G_TYPE_OBJECT)

static void
m_number_class_init (MNumberClass *klass)
{
	klass->add = NULL;
	klass->sub = NULL;
	klass->mul = NULL;
	klass->div = NULL;
	klass->uminus = NULL;
	klass->to_str = NULL;
}

static void
m_number_init (MNumber *inst)
{ }

MNumber *
m_number_add (MNumber *self, MNumber *other)
{
	g_return_val_if_fail (M_IS_NUMBER (self), NULL);
	g_return_val_if_fail (M_IS_NUMBER (other), NULL);
	
	MNumberClass *class_ = M_NUMBER_GET_CLASS (self);
	return class_->add ? class_->add (self, other) : NULL;
}

MNumber *
m_number_sub (MNumber *self, MNumber *other)
{
	g_return_val_if_fail (M_IS_NUMBER (self), NULL);
	g_return_val_if_fail (M_IS_NUMBER (self), NULL);
	
	MNumberClass *class_ = M_NUMBER_GET_CLASS (self);
	return class_->sub ? class_->sub (self, other) : NULL;
}

MNumber *
m_number_mul (MNumber *self, MNumber *other)
{
	g_return_val_if_fail (M_IS_NUMBER (self), NULL);
	g_return_val_if_fail (M_IS_NUMBER (other), NULL);
	
	MNumberClass *class_ = M_NUMBER_GET_CLASS (self);
	return class_->mul ? class_->mul (self, other) : NULL;
}

MNumber *
m_number_div (MNumber *self, MNumber *other)
{
	g_return_val_if_fail (M_IS_NUMBER (self), NULL);
	g_return_val_if_fail (M_IS_NUMBER (other), NULL);
	
	MNumberClass *class_ = M_NUMBER_GET_CLASS (self);
	return class_->div ? class_->div (self, other) : NULL;
}

MNumber *
m_number_uminus (MNumber *self)
{
	g_return_val_if_fail (M_IS_NUMBER (self), NULL);
	
	MNumberClass *class_ = M_NUMBER_GET_CLASS (self);
	return class_->uminus ? class_->uminus (self) : NULL;
}

char *
m_number_to_str (MNumber *self)
{
	g_return_val_if_fail (M_IS_NUMBER (self), NULL);
	
	MNumberClass *class_ = M_NUMBER_GET_CLASS (self);
	return class_->to_str ? class_->to_str (self) : NULL;
}

2. 派生类 MInt

m_int.h:

#ifndef M_INT_H
#define M_INT_H

#include <glib-object.h>
#include "m_number.h"

#define M_TYPE_INT  (m_int_get_type())
G_DECLARE_FINAL_TYPE (MInt, m_int, M, INT, MNumber)

MInt *
m_int_new_with_value (int value);

MInt *
m_int_new (void);

#endif // M_INT_H

m_int.c:

#include "m_int.h"
#include "m_double.h"

#define PROP_INT 1
static GParamSpec *int_property = NULL;

struct _MInt {
	MNumber base_class;
	int value;
};

G_DEFINE_TYPE (MInt, m_int, M_TYPE_NUMBER)

static void
m_int_set_property (GObject *object,
                    guint property_id,
                    const GValue *value,
                    GParamSpec *pspec)
{
	MInt *self = M_INT (object);
	
	if (property_id == PROP_INT)
		self->value = g_value_get_int (value);
	else
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}

static void
m_int_get_property (GObject *object,
                    guint property_id,
                    GValue *value,
                    GParamSpec *pspec)
{
	MInt *self = M_INT (object);
	
	if (property_id == PROP_INT)
		g_value_set_int (value, self->value);
	else
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}

static void
m_int_init (MInt *d)
{ }

#define m_int_binary_op(op)\
    int i;\
    double d;\
    if (M_IS_INT (other)) {\
        g_object_get (M_INT (other), "value", &i, NULL);\
        return M_NUMBER (m_int_new_with_value (M_INT (self)->value op i));\
    } else {\
        g_object_get (M_DOUBLE (other), "value", &d, NULL);\
        return M_NUMBER (m_int_new_with_value (M_INT (self)->value op (int)d));\
    }

static MNumber *
m_int_add (MNumber *self, MNumber *other)
{
	g_return_val_if_fail (M_IS_INT (self), NULL);
	m_int_binary_op (+)
}

static MNumber *
m_int_sub (MNumber *self, MNumber *other)
{
	g_return_val_if_fail (M_IS_INT (self), NULL);
	m_int_binary_op (-)
}

static MNumber *
m_int_mul (MNumber *self, MNumber *other)
{
	g_return_val_if_fail (M_IS_INT (self), NULL);
	m_int_binary_op (*)
}

static MNumber *
m_int_div (MNumber *self, MNumber *other)
{
	g_return_val_if_fail (M_IS_INT (self), NULL);
	m_int_binary_op ( /)
}

static MNumber *
m_int_uminus (MNumber *self)
{
	g_return_val_if_fail (M_IS_INT (self), NULL);
	
	return M_NUMBER (m_int_new_with_value (-M_INT (self)->value));
}

static char *
m_int_to_str (MNumber *self)
{
	g_return_val_if_fail (M_IS_INT (self), NULL);
	int i;
	
	g_object_get (M_INT (self), "value", &i, NULL);
	return g_strdup_printf ("%d", i);
}

static void
m_int_class_init (MIntClass *class_)
{
	MNumberClass *mnumber_class = M_NUMBER_CLASS (class_);
	GObjectClass *gobject_class = G_OBJECT_CLASS (class_);
	
	mnumber_class->add = m_int_add;
	mnumber_class->sub = m_int_sub;
	mnumber_class->mul = m_int_mul;
	mnumber_class->div = m_int_div;
	mnumber_class->uminus = m_int_uminus;
	mnumber_class->to_str = m_int_to_str;
	
	gobject_class->set_property = m_int_set_property;
	gobject_class->get_property = m_int_get_property;
	int_property = g_param_spec_int (
	                   "value", "val", "Integer value",
	                   G_MININT, G_MAXINT, 0, G_PARAM_READWRITE
	               );
	g_object_class_install_property (gobject_class, PROP_INT, int_property);
}

MInt *
m_int_new_with_value (int value)
{
	return g_object_new (M_TYPE_INT, "value", value, NULL);
}

MInt *
m_int_new (void)
{
	return g_object_new (M_TYPE_INT, NULL);
}

3. 派生类MDouble

m_double.h:

#ifndef M_DOUBLE_H
#define M_DOUBLE_H

#include <glib-object.h>
#include "m_number.h"

#define M_TYPE_DOUBLE   (m_double_get_type())
G_DECLARE_FINAL_TYPE (MDouble, m_double, M, DOUBLE, MNumber)

MDouble *
m_double_new_with_value (double value);

MDouble *
m_double_new (void);


#endif // M_DOUBLE_H

m_double.c:文章来源地址https://www.toymoban.com/news/detail-421021.html

#include "m_double.h"
#include "m_int.h"

#define PROP_DOUBLE 1
static GParamSpec *double_property = NULL;

struct _MDouble {
	MDouble base_class;
	double value;
};

G_DEFINE_TYPE (MDouble, m_double, M_TYPE_NUMBER)

static void
m_double_set_property (GObject *object,
                       guint property_id,
                       const GValue *value,
                       GParamSpec *pspec)
{
	MDouble *self = M_DOUBLE (object);
	if (property_id == PROP_DOUBLE)
		self->value = g_value_get_double (value);
	else
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}

static void
m_double_get_property (GObject *object,
                       guint property_id,
                       GValue *value,
                       GParamSpec *pspec)
{
	MDouble *self = M_DOUBLE (object);
	if (property_id == PROP_DOUBLE)
		g_value_set_double (value, self->value);
	else
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}

static void
m__double_init (MDouble *d)
{ }

#define m_double_binary_op(op)\
    int i;\
    double d;\
    if (M_IS_INT (other)) {\
        g_object_get (M_INT (other), "value", &i, NULL);\
        return M_NUMBER (m_double_new_with_value (M_DOUBLE (self)->value op (double) i));\
    } else {\
        g_object_get (M_DOUBLE (other), "value", &d, NULL);\
        return M_NUMBER (m_double_new_with_value (M_DOUBLE (self)->value op d));\
    }

static MNumber *
m_double_add (MNumber *self, MNumber *other)
{
	g_return_val_if_fail (M_IS_DOUBLE (self), NULL);
	
	m_double_binary_op (+)
}

static MNumber *
m_double_sub (MNumber *self, MNumber *other)
{
	g_return_val_if_fail (M_IS_DOUBLE (self), NULL);
	
	m_double_binary_op (-)
}

static MNumber *
m_double_mul (MNumber *self, MNumber *other)
{
	g_return_val_if_fail (M_IS_DOUBLE (self), NULL);
	
	m_double_binary_op (*)
}

static MNumber *
m_double_div (MNumber *self, MNumber *other)
{
	g_return_val_if_fail (M_IS_DOUBLE (self), NULL);
	
	m_double_binary_op ( /)
}

static MNumber *
m_double_uminus (MNumber *self)
{
	g_return_val_if_fail (M_IS_DOUBLE (self), NULL);
	
	return M_NUMBER (m_double_new_with_value (- M_DOUBLE (self)->value));
}

static MNumber *
m_doube_to_str (MNumber *self)
{
	g_return_val_if_fail (M_IS_DOUBLE (self), NULL);
	double d;
	
	g_object_get (M_DOUBLE (self), 'value', &d, NULL);
	return g_strdup_printf ("%lf", d);
	
}
static void
m_double_class_init (MDoubleClass *class_)
{
	MNumberClass *mnumber_class = M_NUMBER_CLASS (class_);
	GObjectClass *gobject_class = G_OBJECT_CLASS (class_);
	
	mnumber_class->add = m_double_add;
	mnumber_class->sub = m_double_sub;
	mnumber_class->mul = m_double_mul;
	mnumber_class->div = m_double_div;
	mnumber_class->uminus = m_double_uminus;
	mnumber_class->to_str = m_doube_to_str;
	
	gobject_class->set_property = m_double_set_property;
	gobject_class->get_property = m_double_get_property;
	
	double_property = g_param_spec_double (
	                      "value", "val", "Double value",
	                      -G_MAXDOUBLE, G_MAXDOUBLE, 0, G_PARAM_READWRITE
	                  );
	g_object_class_install_property (gobject_class, PROP_DOUBLE, double_property);
}

MDouble *
m_double_new_with_value (double value)
{
	return g_object_new (M_TYPE_DOUBLE, "value", value, NULL);
}

MDouble *
m_double_new (void)
{
	return g_object_new (M_TYPE_DOUBLE, NULL);
}

到了这里,关于3.派生类和抽象类的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 资料与参考

    资料: 本书(《Python神经网络编程》)的资料是使用Jupyter notebooks写的,本人并不擅长使用Jupyter,所以用传统py重写了一遍,并附加了新功能(即多数字识别),现将Jupyter版和py版连带本书pdf一并上传至gitee,地址:python-neuralNetwork-coding: 《Python神经网络编程》pdf和随书源码,

    2024年02月11日
    浏览(43)
  • Fast Planner——代码解读参考资料整理

    参数解读 主要函数解读 概率栅格地图,概率更新过程的公式推导过程 全概率公式、贝叶斯公式 一. kinodynamic a_star(前端hybrid A_star动力学路径搜索) 1.1启发函数的计算 1.2 Compute shot Traj 1.3 节点扩张 1.4 节点剪枝 1.5 返回kinopath与 getsamples 二、B样条曲线设置 2.1 均匀B样条设置

    2024年02月05日
    浏览(77)
  • [渝粤教育] 中国人民警察大学 工业企业防火 参考 资料

    教育 -工业企业防火-章节资料考试资料-中国人民警察大学【】 随堂测验 1、【判断题】工业企业的火灾特点是涉及行业种类繁多,涉及到社会生活的方方面面。 A、正确 B、错误 参考资料【 】 2、【判断题】工业企业的火灾特点是物资集中,存在各种形式的点火源,发生火灾

    2024年02月02日
    浏览(49)
  • [渝粤教育] 辽宁对外经贸学院 数字新技术 参考 资料

    教育 -数字新技术-4-章节资料考试资料-辽宁对外经贸学院【】 第一单元测验 1、【单选题】1. 云计算是对(D)技术的发展与运用 云计算是对( )技术的发展与运用。 A、并行计算 B、网格计算 C、分布式计算 D、三个选项都是 参考资料【 】 2、【单选题】从研究现状上看,下

    2023年04月25日
    浏览(51)
  • 3.派生类和抽象类

    参考资料:https://github.com/ToshioCP/Gobject-tutorial/blob/main/gfm/sec6.md 抽象类型没有任何实例。 G_DECLARE_DERIVABLE_TYPE 宏用来声明抽象类。这类似于 G_DECLARE_FINAL_TYPE 宏。 比如面的例子, MNuber 是抽象类, G_DECLARE_DERIVABLE_TYPE 扩展为: 函数声明 m_number_get_type() ,你需要定义它。你可以用

    2023年04月22日
    浏览(21)
  • 【Python NLTK】零基础也能轻松掌握的学习路线与参考资料

    Python 自然语言处理工具包(Natural Language Toolkit,简称 NLTK)是一款 Python 的库,主要用于处理自然语言的相关问题,如文本清洗、标记化、分词、语义分析、词性标注、文本分类等功能,是数据科学家和机器学习工程师不可或缺的工具之一。 本文将介绍学习 Python NLTK 的路线,

    2024年02月07日
    浏览(46)
  • 【Python psycopg2】零基础也能轻松掌握的学习路线与参考资料

    Python psycopg2是一个Python库,在Python中提供了一个连接PostgreSQL数据库的接口。它可以让Python应用程序和PostgreSQL数据库之间进行通信和数据传输。学习Python psycopg2的路线和教程可以在查阅资料和实践中快速入门。 一、学习前置知识 学习Python psycopg2需要一定的前置知识,如Pytho

    2024年02月05日
    浏览(39)
  • 【Python Cookie 和代理 IP】零基础也能轻松掌握的学习路线与参考资料

    一、Python Cookie 1、什么是Cookie? Cookie是一种在客户端保存数据的机制,服务器通过在HTTP响应头中添加Set-Cookie头实现。浏览器在接收到响应头中的Set-Cookie后,会将这个Cookie保存在本地。之后每次请求都会将本地保存的Cookie自动添加到请求头中,发送给服务器。 2、为什么需要

    2024年02月05日
    浏览(36)
  • 基于python影视电影点评系统设计与实现:开题报告、成品参考、毕设辅导资料

     博主介绍: 《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育和辅导。 所有项目都配有从入门到精通的基础知识视频课程,免费 项目配有对应开发文档、开题报告、任务书、PPT、论文模版

    2024年02月05日
    浏览(37)
  • 基于JAVA高校校园学习资料共享系统 设计与实现(springboot框架) 参考文献

     博主介绍 :黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育和辅导。 所有项目都配有从入门到精通的基础知识视频课程,免费 项目配有对应开发文档、开题报告、任务书、

    2024年01月19日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包