It is a well known fact that the snippet below prints Derived or something similar.
#include<iostream>
#include<typeinfo>
class Base { public: virtual ~Base(){} };
class Derived : public Base{};
int main()
{
Derived d;
Base& b = d;
std::cout << typeid(b).name() << '\n';
}
But I'd like to understand how could one conclude this, from paragraph §5.2.8/2 in the Standard (N4140). For example, b is certainly a glvalue, but the type Base& is not the same as Base, so I can't say that b is polymorphic. What am I missing?
From [expr]
If an expression initially has the type “reference to T” (8.3.2, 8.5.3), the type is adjusted to T prior to any further analysis. The expression designates the object or function denoted by the reference, and the expression is an lvalue or an xvalue, depending on the expression.
The expression b initially has type "reference to Base", so the type is adjusted to Base. It is an lvalue, which is a glvalue.
From [class.virtual]:
A class that declares or inherits a virtual function is called a polymorphic class.
Base declares a virtual function, so it is a polymorphic class.
From [expr.typeid]:
When
typeidis applied to a glvalue expression whose type is a polymorphic class type (10.3), the result refers to astd::type_infoobject representing the type of the most derived object (1.8) (that is, the dynamic type) to which the glvalue refers.
Based on the above, we satisfy the initial conditions (the expression is a glvalue whose type is a polymorphic class type), so we pick the most derived object to which b refers to. That would be d, which has type Derived.
If b were a Base instead of a Base&, then the most derived object would be b itself.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With