Dr. Dobb’s Journal issue of March 2003 features an article comparing C++’s libsigc++ class library to C#’s delegate feature.
Dr. Dobb’s Journal issue of March 2003 features an article comparing C++’s libsigc++ class library to C#’s delegate feature.
Interesting no c++ native gui libs I know of implement libsigc++ as their callback mechanism. I always thought they were pretty neat, a far superior way of doing callbacks compared to Qt’s older method.
If I’m wrong please mention it. And note I did say “native” c++ gui libs, not wrappers.
Indeed, gtkmm does it AFAIK, but gktmm is a wrapper…
Eugenia, libsigc++ was spawned from Gtkmm, back when it still was called Gtk–. This is taken from the rpm description of libsigc++ 1.2.4:
This library implements a full callback system for use in widget libraries, abstract interfaces, and general programming. Originally part of the Gtk– widget set, [libsigc++] is now a seperate library to provide for more general use. It is the most complete library of its kind with the ablity to connect an abstract callback to a class method, function, or function object. It contains adaptor classes for connection of dissimilar callbacks and has an ease of use unmatched by other C++ callback libraries.
Ah, thanks for the info. I knew gtkmm had something to do wiht it, but I wasn’t sure, as I never really tried or got involved with gtkmm extensively.
Don’t forget that “moc” also provides basic introspection capabilities to the objects it touches. This means that you can find out what functions a generic QObject has without knowing what type it really is at compile time. This is very useful for writing scripting language bindings and such things. Basically with Qt you end up with a nice component model (comparable to Microsoft COM or OpenOffice’s UNO) without the pain of doing horrible things in assembler.
That said, libsig++ is very cool (and solves a different problem to the one I just described ;-)).
Ralph
From the article:
The libsigc++ library lets you define C++ Signal objects
I wish people wouldn’t create things like this, using a name that’s identical to an existing class or keyword, but with different case. At least until we get a case-sensitive version of Google ๐
libsigc++ just demonstrates a bit of the power of C++ templates. The real interesting thing about this article is not that the two mechanisms have about the same easy of use and language integration, but one is implemented entirely outside the language as a library, while the other is internal to the language. The Boost C++ libraries, at http://www.boost.org have been demonstrating these advanced techniques for a long time. The Boost libraries have gotten to the point where they have one library (Spirit), that is a complete parser generator that has the grammers specified entirely in C++ code. They even have a lambda library that provides anonymous functions (which, admittedly, aren’t totally transparent until we get real language support) and higher order functions. Of course, all this provides ample firepower to allow someone to blow their leg off with it. Unfortunately, people often go “let’s see, what use can I find for this feature” approach rather then having a problem, and surveying the C++ soluation space to find the best solution.
As for GUI libraries, the main reason most current systems use C++ as a compiled Java (ie: vanilla OOP) is because it wasn’t until recently that good C++ compilers became widespread. Visual C++ blows horrendously when it comes to C++ code. It pretty much doesn’t have any support for templates beyond the “container of T” stuff. GCC 2.95.x is better, but not great. GCC 3.2.x and Visual C++ 7.1 (beta, at the moment) are nearly perfect, Intel C++ 7.0 is almost as good, and Comeau C++ is pretty much definitively correct. Modern C++ techniques, though, would be good in a C++ library. I was thinking the other day of a constraint-based layout manager (constraint mechanisms are often used in CAD systems). I was thinking that you could add mathematical relationships between two objects by passing an equation via a string. Then I realized the string approach is stupid. Why write my own little mini language when I can just use Boost.Lambda and pass a higher order function!
Regardless of whether or not the various *mm libraries are wrappers or not, that are all pretty darned lovely to work with, libsigc++ is just one part of a pretty nice picture.
I’d also have to agree with the poster that mentioned Boost, frankly you could print some of thier example out onto canvas and hang them on your walls.
Well, as a well-known developer (in BeOS circles), I guess I should say something. SO here goes….
WTF!?
–The loon
Who are you?
I don’t know who you are.
Just for comparision, consider the Object Pascal syntax (Delphi/Kylix etc):
type MyCallback: function (Param1: integer; var Param2: string): integer of object;
(the “of object” is all that seperates it from a normal non-object callback prototype.
Very very elegant.
I don’t know C#, but I find strange to put on the same side delegates and signals. For me, delegating is a design pattern
It’s heavily used in Cocoa/GNUstep. For example, with the NSTableView’s widget (used to draw tables), you don’t create subclasses when you want to specialize its behavior or set its content (like you would do in others C++ gui libs). You create a delegate object which is responsible of providing some methods, used by NSTableView to draw itself. For example, the delegate is asked when the user click on a NSTableView’s cell…
There is the same mechanism to provide the “data source” of NSTableView. The delegate then responds for example to “questions” like “how many columns I have ?”, “what’s in the column 3 row 2”, etc., and NSTableView ask it.
The big difference between delegating and subclassing is that with delegating you don’t need to know the internal of the object (here NSTableView), thus it’s cleaner and simpler to use delegating rather than subclassing when it’s possible. An interessting design pattern. Of course, it doesn’t apply everywhere, and in the case of gui libs, the lib must be designed to support it (that’s the case of Cocoa/GNUstep), but it’s really a nice thing.
egin{language-trolling}
On the language side, in ObjectiveC (the default language for Cocoa/GNUstep frameworks, even if others are possible such as Java or Ruby), everything is signals, and everything is dynamic. Sending a message “toto” to an object is simple : [myObject toto] …
Thoses brackets are the only syntactical change with ObjectiveC compared to plain old C … and it only means that you send a signal. The receiver is on the left, the signal on the right. You could of course imbricate brackets …
And as everything is dynamic, you could ask at runtime if an object support a particular method, ask the type of the object, etc. As everything is an object, polymorphism is natural. Imho this syntax is vastly cleaner and simpler than the complex one used in C# or C++ …
end{language-trolling}
The same thing can be done in C++ by using either callbacks, templates (although this can get messy) or simple virtuals. Objective-C has the advantage of being able to look up the method by name at runtime so the extra step by using virtuals can be avoided but this isn’t comparable to C# delegates or C++ callbacks since the delegate object handles all of the delegation whereas C# delegates and C++ callbacks only deal with a specific “delegation”.
GUI libraries based on subclassing for event handling and widget behaviour is bad form, this shouldn’t be needed and if you look at the two most common GUI toolkits on X11 at the least, GTK+ and QT, you seldom do subclassing.
I think the biggest difference between Objective-C and C++ is that C++ is a new language, Objective-C is more of a really fancy preprocessor to C with a semifunctional runtime. Or at least that his how it’s currently done.
Looncraz is a developer on the Zeta project (i think).
Object Pascal wins hands doen over C++ on this front.
There are now many implementations to choose from – no excuse not to look at ut. Free Pascal (Windows, Dos, Linux, at least one BSD, Amiga, BeOS, QNX, Solaris etc on x86, and soon PPC), and Virtual Pascal (OS/2, Linux, Windows), all of which are to a greater extent Borland Object Pascal compatible.
Anders Hjelsberg (sp?) was the originator/main architect of the Delphi Object Pascal language, so it’s not surprising that so many of the good ideas feom Delphi made it into C# over that nasties of C++.
It makes me wonderwhy so many are willing to write of OP without trying it…
The same thing can be done in C++ by using either callbacks, templates (although this can get messy)
Of course ! but as you said … “it can get messy” and imho that’s the whole point.
the delegate object handles all of the delegation whereas C# delegates and C++ callbacks only deal with a specific “delegation”.
? Well I don’t see your point … using an unique “delegate” object for each widget is just related to the design of the OpenStep framework, it’s not related at all to ObjectiveC !
Widgets are just designed to send messages to a delegate object if there is one.
GUI libraries based on subclassing for event handling and widget behaviour is bad form, this shouldn’t be needed and if you look at the two most common GUI toolkits on X11 at the least, GTK+ and QT, you seldom do subclassing.
It was a long time ago when I did Qt programming, but QTable subclassing for example is quite common… see http://doc.trolltech.com/3.1/table-examples.html …
I don’t say it’s difficult, but that’s the way of doing things in many gui toolkits. What I just pointed is that using a delegate object is imho cleaner. And I wrote that only because for me “delegate” is a design pattern, and not some vocable to say “signal”
I think the biggest difference between Objective-C and C++ is that C++ is a new language, Objective-C is more of a really fancy preprocessor to C with a semifunctional runtime. Or at least that his how it’s currently done.
Oh, that’s a bad trolling I’d hope a better one.
Why Objective-C isn’t “a new language” and just a “fancy preprocessor” ? C++ is also a “fancy preprocessor” to C if
you take this point of view
On a more serious note, the basic difference between Objective-C and C++ is the different OO approach. Objective-C take the SmallTalk way (dynamism), C++ is more on the Simula side (statically compiled). Each one has advantages. But imho for GUI-programming, dynamism is a better choice.
First-class functions would eliminate the need for such kludges.
It’s understandable that C++ doesn’t have them, considering that its runtime is extremely low-level, but for languages like C# (or Java, for that matter), not having such a powerful language feature is simply a big mistake.
What Nicolas Roard is describing is the Gang of Four decorator pattern, aka delegation. C# delegates (and libsigc++ callbacks) are similar to this concept, but not exactly. “Delegate” is a good word, actually, but a confusing one given the existing design pattern usage.
A decorator requires creating a new delegator class that exposes the same interface as the delegated class, and intercepting method calls to modify behaviour. C# delegates, for one, do not involve creating such a new class. A delegate is a single method.
Think of delegates “event handlers” or “callbacks”. Something like:
class MyApp
{
MyApp()
{
Widget w = new Widget();
w.onPaint = customPaint;
}
void customPaint(Object sender, Rectangle rect)
{
// Custom paint code here
}
}
(Does this forum display line breaks and indentation correctly? I’ll know soon enough!)
In C#, onPaint is actually a collection of delegates, so you can do:
w.onPaint += customPaint;
w.onPaint += anotherCustomPaint;
I don’t know much about C#, but I assume the runtime internally explodes a call to onPaint() into a call to all registered delegates in sequence.
C#, coming from the Java/Pascal mold, does have the advantage of being visually simple, whereas libstdc++ code is riddled with the obfuscating punctuation that has always been the bane of C++. (As another poster points out, the delegates mechanism actually come from Object Pascal, C# having been co-masterminded by Borland’s creator Anders Hejlsberg.)
A decorator requires creating a new delegator class that exposes the same interface as the delegated class, and intercepting method calls to modify behaviour. C# delegates, for one, do not involve creating such a new class. A delegate is a single method.
In Objective-C you don’t need to subclass anything to have delegate objects. Dispatch is done at runtime unlike C++ and no interface is needed. Either an object has the method by a particular name implemented or it doesn’t, it’s class has nothing to do with it.
In Pascal and C (and C++) a callback is a pointer to a function. One word.
In Object Pascal a class callback is an instance pointer and a pointer to a function. Two words. Twice as long to call-ish.
Very very simple.
๐
> In Object Pascal a class callback is an instance pointer
> and a pointer to a function. Two words. Twice as long to
> call-ish.
That is an out and out falsehood. There is absolutely no difference in the time it takes Object Pascal code, compiled with Delphi, to execute a method *or* a method pointer. No difference at all. The difference is made by *polymorphism* and *inheritence*. If you mark a method as virtual, *that* is when things start slowing down, but there is no speed decrease whether that method is called directly or via a method pointer.
Consider the following benchmark in Delphi 5:
time taken to call this method 1000 times:
function XXX.mul( a, b: integer): integer;
begin
Result := a * b;
end;
direct static method call : 232 miliseconds
static method pointer: 232 miliseconds
direct “virtual” method call: 234 miliseconds
“virtual” method pointer: 234 miliseconds
direct “dynamic” method call: 803 miliseconds
“dynamic” method pointer: 803 miliseconds
This is on a PIII 1Ghz
The point is that, unlike C++, Object Pascal has two VMT’s, the Virtual Method table and the Dynamic method table. The DMT slower, but more compact (chains through inheritence to find correct instance method) but the VMT is blindingly quick.
It’s also worth noting that another advantage Object Pascal has over C++ is that it fixes up the method offsets for the classes is has on the fly as your application starts, so that you will never get the C++ padding problems, and also you get the speed advantage as demonstrated above.
Please do a little research next time ๐
> From the article:
> The libsigc++ library lets you define C++ Signal objects
> I wish people wouldn’t create things like this, using a name
> that’s identical to an existing class or keyword, but with
> different case. At least until we get a case-sensitive
> version of Google ๐
What keyword do you mean? “signal” is not a C++ keyword as far as I know. It might be a keyword in Qt’s extended C++ language, but that’s nothing to do with libsigc++.
And don’t get me started on Qt’s #define of “emit” as an empty macro.