简体   繁体   中英

Performance When Extending Classes, Composition vs Polymorphism

When extending a class, is there any difference in between polymorphism and composition? 是否有差异? Take the following example using composition (in C++):

class Window
{
    public:
        Window(Renderer &renderer) : m_renderer(renderer)
        { }

        void update()
        {
            ....
            m_renderer.draw(this);
        }
    private:
        Renderer &m_renderer;
}

... and using polymorphism:

class Window : public Renderer
{
    public:
        virtual ~Window() {};

        void update()
        {
            ...
            draw();
        }
    protected:
        virtual void draw() = 0;
}

The composition version uses a reference as a member so I suppose that it requires a little more space, but is there any performance gain in either version?

Note: I have checked out similar post such as this , but is does not cover performance.

Thank you for your answers!

Well, if you pose the question like this, then yes there is a memory/speed trade-off.

1. Composition

  • 8 bytes (on 64 bits architecture) are likely to be used for the reference

2. Inheritance

  • 8 bytes (on 64 bits architecture) if you need to make your class polymorphic (v-pointer)
  • some overhead for the attributes of the base class if any (note: inheriting from stateful classes is a code smell)
  • ~20% overhead for the virtual call (gross estimate, lots of variation there)

So you might say that inheritance is slightly more costly... but really it's just invisible. The overhead of a function call compared to the inner computation required for graphic rendering is just negligible.


On the other hand, the semantics differ. Whether you inherit or not is significant. Is you Window a Renderer ? Does it make sense ?

Write sane code first. Then optimize as (if !!!) needed.

I suppose you want the second version to be:

class Window : public Renderer

in which case, the memory by inheritance will actually be bigger. That's because, when you inherit something, the class increases in size by at least the sizeof the base class.

The first version actually only suffers a minor increase in size, as you're storing a reference and not an actual object. The following:

class Window
{
    public:
        Window(Renderer &renderer) : m_renderer(renderer)
        { }

        void update()
        {
            ....
            m_renderer.draw(this);
        }
    private:
        Renderer m_renderer; //no reference
}

would take up more space.

More important than anything when deciding between these two is not performance-wise (differences are minor, if at all), but the relationship between the two. Composition and inheritance describe different things.

If a Window is a Renderer , use inheritance. If a Windows has a Renderer , use composition.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM