I was trying to figure out with what signatures C++ actually calls methods virtually, instead of using the base class. So I wrote the following:
#include <iostream>
#include <string>
using namespace std;
#define GREETER(type, op)\
string greet(type t) {\
return string(#type) + t op greet();\
}
struct Unvirtual {
string greet() {
return "Unvirtual";
}
};
struct UnvirtualUnoverride : Unvirtual {
string greet() {
return "UnvirtualUnoverride";
}
};
struct Virtual {
virtual string greet() {
return "Virtual";
}
};
struct VirtualUnoverride : Virtual {
virtual string greet() {
return "VirtualUnoverride";
}
};
struct VirtualOverride : Virtual {
virtual string greet() override {
return "VirtualOverride";
}
};
GREETER(Unvirtual, .)
//GREETER(Unvirtual&, .)
GREETER(Unvirtual*, ->)
// GREETER(UnvirtualUnoverride, .)
// GREETER(UnvirtualUnoverride&, .)
// GREETER(UnvirtualUnoverride*, ->)
GREETER(Virtual, .)
//GREETER(Virtual&, .)
GREETER(Virtual*, ->)
// GREETER(VirtualUnoverride, .)
// GREETER(VirtualUnoverride&, .)
// GREETER(VirtualUnoverride*, ->)
// GREETER(VirtualOverride, .)
// GREETER(VirtualOverride&, .)
// GREETER(VirtualOverride*, ->)
#define DEBUG(expr)\
cout << #expr << endl;\
cout << "\t" << expr << endl;
int main() {
Unvirtual uv, &uvr = uv, *uvp = &uv;
UnvirtualUnoverride uvu, &uvur = uvu, *uvup = &uvu;
Virtual v, &vr = v, *vp = &v;
VirtualUnoverride vu, &vur = vu, *vup = &vu;
VirtualOverride vo, &vor = vo, *vop = &vo;
DEBUG(greet(uv));
DEBUG(greet(uvr));
DEBUG(greet(uvp));
DEBUG(greet(uvu));
DEBUG(greet(uvur));
DEBUG(greet(uvup));
DEBUG(greet(v));
DEBUG(greet(vr));
DEBUG(greet(vp));
DEBUG(greet(vu));
DEBUG(greet(vur));
DEBUG(greet(vup));
DEBUG(greet(vo));
DEBUG(greet(vor));
DEBUG(greet(vop));
system("pause");
return 0;
}
The program's output was:
greet(uv)
UnvirtualUnvirtual
greet(uvr)
UnvirtualUnvirtual
greet(uvp)
Unvirtual*Unvirtual
greet(uvu)
UnvirtualUnvirtual
greet(uvur)
UnvirtualUnvirtual
greet(uvup)
Unvirtual*Unvirtual
greet(v)
VirtualVirtual
greet(vr)
VirtualVirtual
greet(vp)
Virtual*Virtual
greet(vu)
VirtualVirtual
greet(vur)
VirtualVirtual
greet(vup)
Virtual*VirtualUnoverride
greet(vo)
VirtualVirtual
greet(vor)
VirtualVirtual
greet(vop)
Virtual*VirtualOverride
Press any key to continue . . .
From this I conclude that C++ only dispatches method m
on object o
dynamically when: m
is declared virtual
and o
is a pointer.
Are these conclusions accurate? Have I missed any tests?