Virtual member function changes result of typeid - why?

Viewed 51

this code is working fine and prints "yes":

#include <iostream>
using std::cout;
using std::endl;

class A {
public:
     virtual void talk() {  cout << "person talking" << endl;}
};

class B : public A {
public:
    void work() { cout << "employee working" << endl; }
};

int main() {
    A* pA = new B();

    if (typeid(*pA) == typeid(B))
        cout << "yes" << endl; // this is printed
    else
        cout << "no" << endl;
}

but if i remove the virtual keyword it will print "no"

#include <iostream>
using std::cout;
using std::endl;

class A {
public:
     void talk() {  cout << "person talking" << endl;}
};

class B : public A {
public:
    void work() { cout << "employee working" << endl; }
};

int main() {
    A* pA = new B();

    if (typeid(*pA) == typeid(B))
        cout << "yes" << endl;
    else
        cout << "no" << endl; // this is printed
}

why is that happening?
why does the virtualness of a method impact the type of the object?

EDIT:
To make things more confusing, this works fine:

((B*)(pA))->work(); // works fine, prints "employee working"

So why is the *pA regarded only as class A object (when there is no virtual keyword) but can still call child's work() method?

1 Answers

This is how typeid works. A class that has no virtual members is a non-polymorphic type and carries no run-time type information. Hence there's no way to determine it's type at run time.

See [expr.typeid]/p2:

When typeid is applied to a glvalue expression whose type is a polymorphic class type, the result refers to a std​::​type_­info object representing the type of the most derived object (that is, the dynamic type) to which the glvalue refers.

And [expr.typeid]/p3:

When typeid is applied to an expression other than a glvalue of a polymorphic class type, the result refers to a std​::​type_­info object representing the static type of the expression.

Static type means the type is determined simply at compile-time (for A* it is thus A).

Related