logoalt Hacker News

quotemstrtoday at 1:06 AM1 replyview on HN

What does your explanation have to do with the fact that C++ can express by-value returns of complex objects?


Replies

mpynetoday at 4:52 AM

Everything. The issue is that the compiler won't even bother with polymorphism through a vtable for a polymorphic type (one with a vtable), unless the object is accessed through a pointer or reference.

If you have a value of the type itself (not a pointer or reference), then polymorphism doesn't even enter the equation in C++, even if you initialize from a derived type.

E.g. in this code:

    Base b(m_catalog.makeDerived());
    b.call_virt_func();
Even if `call_virt_func` is declared virtual, it will be `Base::call_virt_func()` that is called here, guaranteed. From a language perspective, we already know that `b` is a `Base`, you literally declared and defined it that way.

Runtime polymorphism is therefore only a game for pointers or references; it is the process of resolving the indirection that even allows for polymorphism to become a thing in C++. But this means that the compiler cannot know the actual type at compile-time for a polymorphic type, unless it can perform devirtualization as an optimization pass.

So although C++ will certainly allow you to define a class method that returns a virtual type by value (and not by pointer or reference), even for complex types, it is almost certainly a bug to do this unless you know for sure what the type will be statically, at compile time. Because the object you create as the return value will be forced to be the return type declared at compile time, "forgetting" the fact that it was created from a type deeper in the inheritance chain. This is the 'slicing problem' that was mentioned in the earlier comment.

show 1 reply