我只是想到了一种在运行时告诉的方法,无需猜测。您可以简单地用 0 覆盖多态类的 vptr 并查看是否调用了该方法或是否遇到分段错误。这就是我的例子:
Concrete: Base
Concrete: Derived
Pointer: Base
Pointer: Derived
DELETING VPTR!
Concrete: Base
Concrete: Derived
Segmentation fault
whereConcrete: T
表示T
通过具体类型调用虚成员函数成功。类似地,Pointer: T
表示T
通过Base
指针调用成员函数是成功的。
作为参考,这是我的测试程序:
#include <iostream>
#include <string.h>
struct Base {
unsigned x;
Base() : x(0xEFBEADDEu) {
}
virtual void foo() const {
std::cout << "Base" << std::endl;
}
};
struct Derived : Base {
unsigned y;
Derived() : Base(), y(0xEFCDAB89u) {
}
void foo() const {
std::cout << "Derived" << std::endl;
}
};
template <typename T>
void dump(T* p) {
for (unsigned i = 0; i < sizeof(T); i++) {
std::cout << std::hex << (unsigned)(reinterpret_cast<unsigned char*>(p)[i]);
}
std::cout << std::endl;
}
void callfoo(Base* b) {
b->foo();
}
int main() {
Base b;
Derived d;
dump(&b);
dump(&d);
std::cout << "Concrete: ";
b.foo();
std::cout << "Concrete: ";
d.foo();
std::cout << "Pointer: ";
callfoo(&b);
std::cout << "Pointer: ";
callfoo(&d);
std::cout << "DELETING VPTR!" << std::endl;
memset(&b,0,6);
memset(&d,0,6);
std::cout << "Concrete: ";
b.foo();
std::cout << "Concrete: ";
d.foo();
std::cout << "Pointer: ";
callfoo(&b);
std::cout << "Pointer: ";
callfoo(&d);
return 0;
}