mropert Polymorphic ducks
NOTE:
1、其实这篇文章是对 Sean Parent的paper的说明
The problem with traditional inheritance
Consider the following:
class Drawable {
public:
virtual ~Drawable() {}
virtual void draw(Display& display) const = 0;
};
Here we have a bunch of objects we want to draw. We can’t know at runtime which ones we will have, only that at some point we will go through a list of them and draw them on a given Display
with a call to draw()
. This is all we care about. But we got a lot more for our trouble:
All of our drawable objects must inherit Drawable
and implement draw()
, which means each of them has to know how to draw itself (or save, or load, or compute or…) which is a clear violation of the principle of separation of concerns1. I could stop there in my list of problems, we already reached the point of no return by coupling our implementation much more that it reasonably should.
But it goes on:
1、We can’t copy-construct or copy-assign our objects anymore, at best we can implement a clone()
virtual method everywhere.
NOTE:
1、virtual clone polymorphic type
2、显然,如果每个地方都需要添加一下的话,那么这就是**intrusive**的。
2、We can’t have a list (or array or set or…) of our objects, we need a list of Drawable*
(or a std::unique_ptr<Drawable>
). It prevents us from using most standard algorithms which expect values and not pointers.
NOTE: 没有理解
3、We can’t store them by value, an owning container will have to new
each one instead of putting them in a contiguous buffer or on the stack, which is terrible for modern CPUs caches.
NOTE:
1、tag-value semantic and reference semantic-stack heap CPU cache-performance
2、value semantic
4、Our code will get cluttered with calls to new
or std::make_unique
everytime we want to create a drawable
.
Alternatives
In his talk at CppCon 2017, Louis Dionne showed a bunch of alternative techniques around that problem which I found interesting but ultimately too complex to present here2.
Instead, I propose we simply use the time tested technique of WWSPD: What Would Sean Parent Do?
NOTE: 其实就是: polymorphic value type idiom
If you answered std::rotate()
, nice try but unfortunately it was not the right answer this time. No, the right answer was presented in his talk: Better Code: Runtime Polymorphism. Here’s how it works:
NOTEl 后面就是开始将implementation,这是炒剩饭,没有什么新意。