为什么创建 GObject 系统?

30

介绍

好的,所以在GTK+的0.60版本之后,设计师们意识到为了未来的发展和进步,整个工具包需要重写为面向对象的。

现在,由于C语言不支持面向对象编程,为了提供面向对象和继承层次结构,他们创建了GObject系统。现在,创建GObject系统肯定需要开发时间、更多依赖和更多问题,但他们必须创建它以为C编程语言提供面向对象的能力。但是当时还有另一种解决方案,可以完全做到这一点,那就是C++

问题

为什么GTK+的开发人员不使用C++呢?

解释

我是说,为什么要浪费时间创建整个库,而不是使用许多项目采用的经过时间考验的解决方案?别误会,我不是想把这篇文章变成C vs C++的争论(我在论坛上已经看够了,谢谢)。我只想知道GTK+设计师做出这个决定的原因和问题。

1
@HansPassant 该项目仍然可以使用C++进行扩展,因为C++与C兼容。 - ApprenticeHacker
1
@IntermediateHacker:大多数情况下,C程序可以被视为C++程序。但这并不是一种严格的关系,因为某些C概念(例如restrict)在C++中不存在。 - Ken Wayne VanderLinde
3
C++并不是具有"对象导向能力"的"C语言副本"。 - Lightness Races in Orbit
GTK并非主要为添加面向对象特性而进行重写...请查看带有维基引用的答案... - user1055604
4个回答

25

我不能直接回答这个问题,至少就GTK而言是这样的。这个答案应该由GTK+开发人员来提供,所以你需要去找他们问。但是关于为什么要给C语言添加面向对象系统,而不是使用C ++,有很多原因。我能想到的三个原因是:

  1. 语言复杂性:虽然C是一种相当简单的语言,但C++则非常复杂,它支持大多数(不是全部)C的东西,以及引用等便利功能,并具有面向对象的特性和复杂的模板语言。你看过新的值系统吗:lvalues、rvalues、glvalues、prvalues和xvalues - 呃?还有很多我可以谈论的内容。在时间充裕的情况下,C++变得可管理,但如果只想在C中使用一些面向对象的特性,那么它仍然是过度设计。

  2. 控制:如果设计者采用了C++,他们将被困在C++哲学中。例如,多重继承是一个有争议的想法,有充分的理由。通过设计,GObject系统仅支持单一继承,这可以大大简化继承层次结构。如果设计者采用了C++,没有办法限制用户只使用单一继承系统。多重继承只是一个例子,我相信在GObject系统与C++意识形态不同的地方还有很多其他地方。

  3. 互操作性:这可能是一个重要的原因。尽管有一些语言可以与C++清晰地互操作,但事实上,C++的互操作性并不是很好。然而,与C的互操作几乎是理所当然的。 C通常被描述为编程语言的世界语,因为它形成了互操作的事实标准。通过设计一个C API,GObject的设计者为在任何数量的语言中开发GTK+打开了大门。


9
@NicolBolas 这个回答代表了GTK开发人员在开发GTK之前可能思考的思路或面临的选择。正如回答者所提到的,答案取决于GTK+开发人员。 - user1055604
2
我认为#3特别有吸引力。C++的绑定可以完成,但对于C来说情况总是稍微好一些。 - Rawler
3
回答问题或者不回答,但是你那些讽刺的评论并没有帮助任何人。 - Lightness Races in Orbit
3
例如,多重继承是一个有争议的想法,这是有道理的。从设计上讲,GObject 系统只支持单一继承,这可以大大简化继承层次结构。但这也是一个站不住脚的理由;他们为什么要关心用户是否使用 MI?这不会影响他们的项目(GIMP),而且 C++ 没有强制使用 MI 的要求。如果你不喜欢它,就不要使用它(这是我的哲学,我从来没有遇到过问题)。 - weberc2
1
@underscore_d 是的,我也一直在关注这个问题,但在编译器、操作系统和基本库上形成临界质量之前,还有很长的路要走。一旦在 extern "abi" 上构建了实际的操作系统内核(而且它不叫 Symbian ;) ),就可以宣告胜利了。 - kert
显示剩余11条评论

16

GObjects旨在独立于语言。它具有动态类型,您应该将其与类似于COM、.NET或CORBA的运行时系统进行比较,而不是与特定语言进行比较。如果你要涉及语言,那么这些特性更接近于Objective-C而不是C++。


13

GObject 类型系统具有 C++ 无法实现的功能。其中一个是允许在运行时创建新类,并以一种与语言无关的方式进行操作。您可以在 Python 中定义一个新类,然后在 C 函数中操作该类的实例,而该函数不需要知道 Python 是否参与其中。


6
或许有点学究气,但在C++中确实可以实现。你的意思是在运行时创建类方面,它并非内置于C++中。 - Sion Sheevok
1
@user894763 能让你做什么,确切地说? - weberc2
1
@user894763 或许我还有些误解,但这似乎有点循环。我的问题实际上是,“为什么需要动态创建类?”,而你的回答实际上是,“为了动态创建类”。你能否更详细地阐述一下为什么有人可能想要动态创建类?为什么这是一个有用的功能? - weberc2
1
抱歉我表达得不够清楚。假设您有一个名为libfoo的库,它不是基于GObject的,并且您想从像JavaScript这样具有成熟的GObject接口的语言中使用它。一种方法是编写少量的C代码来内省libfoo,并(在运行时)生成一组GObject类,每个类对应您想要使用的一个功能。现在,您可以从JS调用libfoo。这里的优点是绑定是在运行时进行的,因此随着功能添加到libfoo,绑定将自动更新。当然,有许多方法可以进行库绑定,但在某些情况下,这可能很有用。 - jcupitt
1
@underscore_d,这是我项目中的一个例子。我维护了一个基于 GObject 的图像处理库:https://github.com/jcupitt/libvips 你可以通过 Ruby、Python 和 JavaScript 的 GObject 绑定来使用它。之前的 vips 版本不是基于 GObject 的,所以你不能使用旧 API 中的操作...但有一种方法可以遍历旧的内省系统并生成 GObject 类,这样你就可以使用旧的 API 了!https://github.com/jcupitt/libvips/blob/be4ffa6d8ac966f5498e1008561114f3996ad11c/libvips/deprecated/wrapvips7.c#L72 - jcupitt
显示剩余5条评论

5
从问题中链接到的维基百科 了解到:

历史(摘自维基百科)

GTK +最初是在GNU图像处理程序(GIMP)中设计和使用,用作Motif工具包的替代品。 在某个时候,Peter Mattis对Motif感到不满,并开始编写自己的GUI工具包,称为GIMP工具包,并且在GIMP的0.60版本中成功地替换了Motif。[3]最后,GTK被重新编写为面向对象,并更名为GTK +。 这是在GIMP的0.99版中首次使用的。


这应该告诉您,“面向对象范例”并不是选择GTK(与GTK +不同)语言的一项重要标准,并且该特性是在较晚时才添加的。


我仍然不明白为什么有人会自己折磨。C++并不是很好,但它比GObject好太多了。:( - weberc2
2
你为什么认为这是一个答案?问题是为什么要用C重新编写,而不是使用C++或其他本地OOP语言。仅告诉我们“它被重新编写”是完全重言。我猜我们应该推断出它不是完全重写,或者核心团队有偏好C的原因 - 这些原因在更好的答案中已经解释了。 - underscore_d
2
这是一个好答案。GIMP是一个C项目。GTK(和GTK +)最初是为The GIMP编写的GUI工具包,因此C是C项目库的自然选择。 GObject从GTK +中提取出来,并保留了C的传统。它仍然是C,因为整个遗产都是C,并且最初是从C程序的C库中提取出来的。在历史的任何时刻,其他语言对于这个目的都没有太多意义。如果最初从头开始编写一个对象系统,可能会有所不同,但它的历史并不是那种项目。 - Taywee
1
它叫做GIMP,而不是The GIMP。The Gimp是Quentin Tarantino电影中的虚构角色。 - Richard Barber

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接