GNOME is a perfect study in how not to architect a software system. Everything about it is wrong.
The first mistake they made was trying to cobble half-assed object-oriented support onto C, rather than just using C++ or Objective-C. Everything about GObject is stupid and counterproductive. It makes writing code a real pain in the ass, since you need to use typecasting macros all over the place. Worse, this sort of code promotes library design that's slow and inefficient. To make it even worse, this style of C code is so convoluted that it is not optimized well by compilers, resulting in binaries that are far slower than they should be.
I don't think the overhead resulting from using C is substantial at all. Maybe you get more overhead than C++ by always using virtual calls but that is offset by not doing C++ magic like unnecessary constructor/destructor calls. You'll have to back this up if you want me to believe you.
You are incorrect here. In C++, if you choose to make virtual calls, you pay the price of indirection via a vtable (this pointer). That's it. You only pay the price in classes which have virtual methods. With GObject, all classes contain a vtable, i.e. all class methods take a pointer to the type instance, which contains within it a pointer to the vtable. Every GObject instance contains this overhead, which makes instantiation of GObject expensive, and additionally increases the memory required for every object. In comparison, you don't pay this overhead for C++ classes unless you actually require it. This isn't including the overhead of additional GObject features such as properties, which are both inefficient to process and are type-unsafe, and the use of "construction properties" in object instantiation. What makes it truly awful is that all this work to implement OO in C is mostly done by hand! You have to manually create your own vtables; you have to manually cast all types to the correct type, and if you get it wrong the compiler won't typically tell you. You have to understand the intricacies of how a C++ compiler works to implement an inferior version in C! Why would anyone willingly inflict this upon themselves?
But this is only the beginning of the GObject problems. When using GObject, the type resolution is done at run-time. Not only does this make programming unsafe--the many typecasts can hide typing issues, leading to failure at run-time rather than at compile-time, it has additional run-time overheads. Here are a few reasons: G_TYPE_CHECK_INSTANCE_CAST, G_TYPE_CHECK_CLASS_CAST, G_TYPE_CHECK_INSTANCE_TYPE, G_TYPE_CHECK_CLASS_TYPE, G_TYPE_INSTANCE_GET_CLASS.
And you'll also need to check every function argument taking a GObject to make sure it's of the correct type with G_TYPE_CHECK_INSTANCE_TYPE (or commonly using a wrapper around it). This is not a cheap operation, it has to check the GType type register, which involves a string lookup in a hash table (GQuark, at least last time I looked). So you have several of those for every function call if you actually investigate the use of all the uppercase casting macros, and again inside the function. This is mostly absent for C++ code (the type checks and casts are done at compile-time), and C++ RTTI involves simple pointer comparisons of typeinfo objects; much faster, and again type-safe.
Here's an example of class using GObject:
This is the same class using C++
The C++ version is type-safe. Several type bugs were found during the C++ conversion, not picked up by the C compiler using GObject. It's more efficient, easier to maintain, and more secure. The objects take up less space in addition. Overall, the C++ conversion had only positive effects. The current implementation is also available in git.
Back in the mid-to-late 90s, when GTK+ was being created, C++ on Linux was poor, and was not yet standardised. This is now no longer the case, it's very well supported and works very well. IMO it would make a lot of sense to make the excellent GTKmm and related mm bindings the real implementation (i.e. not wrapping the C version), which would really improve the quality of the system. Right now, even the GNOME developers do not encourage development using the C interface due to its many problems. Tools like Vala only paper over the problems--you still need to use the C interface to write a "native" GNOME application with access to all the interfaces, because GNOME is still fundamentally tied to the canonical C implementation, with all the problems that entails.