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;
}
