In the code I'm giving you there is E that derives from C, and I have a pointer to an object of C.
#include <iostream>
using namespace std;
class C{
public: virtual C* f(){cout << "C::f()" << endl; return this;}
};
class E: public C{
public: E* f(){cout << "E::f()" << endl; return this;}
};
int main(){
C* pc = new E;
auto p = pc->f();
cout << typeid(p).name() << endl;
}
When I call pc->f() it goes to E::f() due to the virtual function, and I get it, but what is the return type of return this;
?
Because this is a C* but in the signature the method should return an E*. And if you run it it prints:
E::f()
P1C
CodePudding user response:
Here:
class E: public C{
public: E* f(){cout << "E::f()" << endl; return this;}
};
a pointer to E*
is returned. this
is pointer to the current object, an E
.
Because this is a
C*
but in the signature the method should return anE*
.
No, this
is a pointer to E*
and E*
can be converted to C*
. It is called "covariant return type". In a nutshell: It is ok for E::f
to return an E*
even though it overrides C::f
which returns a C*
. That is because E
inherits publicly from C
and E*
can be converted to C*
.
For a caller that expects the signature as declared in C
there is no issue:
void foo(C& c) {
C* p = c.f(); // OK!
}
But then why typeid tells it's a C*?
First of all you need to take care about the names. They are arbitrary. Looking only at the output of a single type name cannot tell with certainty what type it is.
Then you should do this to get the full picture:
cout << typeid(C).name() << endl;
cout << typeid(E).name() << endl;
cout << typeid(p).name() << endl;
cout << typeid(*p).name() << endl;
1C
1E
P1C
1E
p
is a C*
, thats the signature of C::f
the virtual function you called, but the object it points to is an E
.
CodePudding user response:
The type of p
is C*
, but the object it points to is an E
.
If you print the typename of *p
, you get (mangled) E
.
cout << typeid(p).name() << endl << typeid(*p).name() << endl;
When you call f
through an E*
, you get an E*
back.
int main(){
E* pe = new E;
C* pc = pe;
auto p1 = pe->f();
auto p2 = pc->f();
cout << typeid(E).name() << endl << typeid(C).name() << endl;
cout << typeid(p1).name() << endl << typeid(p2).name() << endl;
cout << typeid(*p1).name() << endl << typeid(*p2).name() << endl;
}