假设我想检查一个子类是否已经实现了它的父类的一个虚函数(不管这是否有坏架构的味道......这是一个练习)。如果我想看看两个常规函数是否相同,我可以检查&f == &g
.
// Plain old functions
void f() {}
void g() {}
...
std::cout << "&f " << &f << "\n"; // "1" OK, for some reason func ptrs are converted
std::cout << "&g " << &f << "\n"; // "1" to booleans when printed. I can dig it.
std::cout << "&f == &g " << (&f == &g) << "\n"; // "0" Good, &f and &g are unequal as expected.
但是对于虚拟成员函数,行为是不同的。
// Base class with a virtual
struct A {
virtual void f() {}
};
// Subclass which implements f
struct B : public A {
void f() {}
};
// Subclass which doesn't implement f
struct C : public A {};
...
std::cout << "&A::f " << &A::f << "\n"; // "1"
std::cout << "&B::f " << &B::f << "\n"; // "1"
std::cout << "&C::f " << &C::f << "\n"; // "1" ... okay ... annoying, but alright.
std::cout << "&A::f == &B::f " << (&A::f == &B::f) << "\n"; // "1" DANGER - why does &A::f == &B::f if &f != &g?
std::cout << "&A::f == &C::f " << (&A::f == &C::f) << "\n"; // "1"
std::cout << "&B::f == &C::f " << (&B::f == &C::f) << "\n"; // "1"
std::cout << "(void*)&A::f " << (void*)&A::f << "\n"; // "0x4084b0" Here's what I was actually looking for.
std::cout << "(void*)&B::f " << (void*)&B::f << "\n"; // "0x4084bc" Good - the B::f differs from A::f as it should
std::cout << "(void*)&C::f " << (void*)&C::f << "\n"; // "0x4084b0" Perfect.
std::cout << "(void*)&A::f == (void*)&B::f " << ((void*)&A::f == (void*)&B::f) << "\n"; // "0"
std::cout << "(void*)&A::f == (void*)&C::f " << ((void*)&A::f == (void*)&C::f) << "\n"; // "1"
std::cout << "(void*)&B::f == (void*)&C::f " << ((void*)&B::f == (void*)&C::f) << "\n"; // "0" These are the comparison results I want
所以我的问题在上面的代码中被标记了DANGER
。为什么&A::f == &B::f
如果&f != &g
?有没有办法在不强制转换的情况下进行我想要的比较void*
(这会发出嘈杂的编译器警告-Wpmf-conversions
)?