English 中文(简体)
Just-In-Time Derivation
原标题:

There s a less common C++ idiom that I ve used to good effect a few times in the past. I just can t seem to remember if it has a generally used name to describe it.

It s somewhat related to mixins, CRTP and type-erasure, but is not specifically any of those things.

The problem is found when you want to add some implementation to a class, but you don t want to put it in the class, or any class it derives from. One reason for this might be that the class could be part of an inheritance hierarchy where the implementation should only occur once.

Setting aside, for the the moment, issues such as whether a hierarchy should have concrete non-leaf classes, or whether virtual inheritance may be an option in some cases, I know that one solution to provide the implementation in a template class that derives from its template parameter. This then allows you to use the template when you create an instance, but then only ever use the object by pointer or reference to one of its bases (that s where the type erasure, in a loose sense, comes in).

An example might be that you have an intrusive reference count. All your classes derive from a ref count interface, but you only want the ref count itself, and the implementation of your ref count methods, to appear once, so you put them in the derived template - let s call it ImplementsRC<T>. Now you can create an instance like so:

ConcreteClass* concrete = new ImplementsRC<ConcreteClass>();

I m glossing over things like forwarding constructors formed of multiple templated overloads etc.

So, hopefully I ve made it clear what the idiom is. Now back to my question - is there an accepted, or at least generally used, name for this idiom?

最佳回答

I d definitely consider this to be a mixin, as would Bruce Eckel (http://www.artima.com/weblogs/viewpost.jsp?thread=132988).

In my opinion one of the things that makes this a mixin is that it s still single inheritance, which is different from using MI to achieve something similar.

问题回答

It is an interesting idea. However I am not going to give you the name of an already established pattern here, on the very contrary I am going to explain (somewhat) why I don t think it already has one.

What does it do?

It is a very nice way to avoid the dread diamond inheritance.

Since there is some confusion apparently as to the purpose of the method, let me elaborate why I think this is its purpose:

class RefCounted
{
  virtual void addReference() = 0;
  virtual void removeReference() = 0;
};

class B: public RefCounted {};
class C: public RefCounted {};

class Diamond: public B, public C {};

Now, we here have a problem. If we put the implementation of RefCounted right in this class, it becomes a base-class instead of an interface, and thus we have to use virtual-inheritance or the data members will be duplicated (present in both B and C).

The idea is thus to defer the implementation to the last moment.

Advantages:

  • No need to try to second-guess the use of B or C: virtual inheritance is unnecessary there.
  • The compiler will nicely remind you if you forget to add the implementation, so no need to worry about that.

Inconvenient:

  • Put the burden on the client: you d better have a factory to create your objects, especially since one object may implement various interfaces!!! Note that this might be automated with template meta-programming (more or less) or can simply been provided by the class author.

Example of providing:

// d.h
class D: public B, public C
{
public:
  typedef ImplementRC<D> concrete_type;
  static concrete_type Build(int, int); // Named Constructor idiom

private:
  D(int,int);
}; // class D

// main.cpp
D::concrete_type myD = D::Build(1,2);

So what s the name ?

I can t think of anything that exactly matches this. Bridge and Decorator have been mentionned but this is quite special, and indeed not so OO-oriented (for example it won t happen in Java since you don t have Multi-Inheritance), so I doubt the term is going to be found in the GoF s book.

Also, it s not really the CRTP because there is a kind of loop in the CRTP (base being aware of its derived class) that does not happen here > we indeed are strictly linear!

And then, it s certainly not the Pimpl idiom, which proposes to hide the implementation away from the client while using a template for the implementation just throw it to its face! (The template could use Pimpl as an internal detail though)

I humbly suggest jiti for Just In Time Implementation, which mimicks the title somehow, but is closer to the point I think, derivation here being just a tool rather than a goal.

Interesting idea anyhow.

I m not sure this has a name, as gf suggested it s looks a bit like the bridge pattern. It s almost like your hooking on functionality to the base class.

I suggest a new name for this, the pimp idiom. As you re pimping your base class ;)

Are you looking for the Decorator pattern?

Basically the decorator is an object that encloses another object and extends the functionality of certain methods. The method calls are then forwarded to the enclosed method.

This is a mixin

Looking at your reference counting example, you may get some joy looking into CComObject<> which is one of a few template classes that ATL contains to provide the implementation of IUnknown. It also uses policy classes to vary the behaviour. Naturally the signal-to-noise ratio trying to Google about the concept of CComObject is very low because it s so ubiquitous. This MSDN article may give you some more "keywords" to aid any searching.

http://msdn.microsoft.com/en-us/library/c43h4867(VS.80).aspx

[NB: Just to be clear - I m not suggesting he uses CComObject, I m suggesting it is another popular example of the same concept and therefore may have been referenced in a patterns book or article]

Looks like Pimpl idiom? Maybe used in an unusual way.

I am not sure but is it "empty member c++ optimization" ?

and such kind of behaviour is implemented using class templates and private inheritance.

It is explained in Magazine Article named "Counting Objects in C++" by Scott Meyer.

Answering my own question. First sign of madness? - no there were several signs before this ;-)

Anyway, it s been so long since I originally posted I m more-or-less a different person anyway.

I ve found that I ve settled on the name, mixover. I ve found this fits very nicely and can be considered a refinement of mixin, rather than being exclusive to the more general concept.

I ve been using them a lot recently so I thought I d come back and update this thread.





相关问题
Undefined reference

I m getting this linker error. I know a way around it, but it s bugging me because another part of the project s linking fine and it s designed almost identically. First, I have namespace LCD. Then I ...

C++ Equivalent of Tidy

Is there an equivalent to tidy for HTML code for C++? I have searched on the internet, but I find nothing but C++ wrappers for tidy, etc... I think the keyword tidy is what has me hung up. I am ...

Template Classes in C++ ... a required skill set?

I m new to C++ and am wondering how much time I should invest in learning how to implement template classes. Are they widely used in industry, or is this something I should move through quickly?

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

typedef ing STL wstring

Why is it when i do the following i get errors when relating to with wchar_t? namespace Foo { typedef std::wstring String; } Now i declare all my strings as Foo::String through out the program, ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

Window iconification status via Xlib

Is it possible to check with the means of pure X11/Xlib only whether the given window is iconified/minimized, and, if it is, how?

热门标签