[cairo] cairomm: reference counting v. inheritance

Murray Cumming murrayc at murrayc.com
Sat Dec 17 07:44:29 PST 2005

At the moment, the cairomm classes are reference-counted without the use
of a smartpointer. So, if I do,

Cairo::context a = get_some_context();
Cairo::context b = a;

and then do b.something(), then I've done something to a as well, because
they are the same underlying instance.

This will surprise some people who expect all copy constructors to do
copy-by-value, but it's not so unusual, and I'm afraid that people will
find smartpointer syntax ugly:

Cairo::RefPtr<Cairo::Context> a = get_some_context();
Cairo::RefPtr<Cairo::Context> b = a;

(We do this in gtkmm, but there aren't that many reference-counted
objects, so it doesn't get too annoying)

HOWEVER, the current system makes it difficult to cast between related
types (such as Pattern, or the Surface hierarchy of classes).
Cairo::LinearGradient derived = get_some_gradient();
Cairo::Gradient base = derived; //Actually, this would work, though it's
kind of strange.
Cairo::LinearGradient derived2 =
dynamic_cast<Cairo::LinearGradient>(base); //Not valid syntax.

This works with a (good) RefPtr, like we have in gtkmm:
Cairo::RefPtr<Cairo::LinearGradient> derived = get_some_context();
Cairo::RefPtr<Cairo::Gradient> base = derived;

And from base to derived like so:
Cairo::RefPtr<Cairo::LinearGradient> derived2 =

There's also the issue of constness. A const smartpointer can act like a
const pointer, and prevent an implicit cast to a non-const smartpointer.

I am gradually becoming convinced that we should use a RefPtr. Here's the
patch to do it:

Murray Cumming
murrayc at murrayc.com

More information about the cairo mailing list