Допустим, у меня есть тип указателя, который может содержать адрес метода базового класса. Могу ли я назначить ему адрес метода подкласса и ожидать, что он будет работать правильно? В моем случае я использую его с указателем базового класса, а динамический тип объекта - это производный класс.
struct B
{
typedef void (B::*MethodPtr)();
};
struct D: public B
{
void foo() { cout<<"foo"<<endl; }
};
int main(int argc, char* argv[])
{
D d;
B* pb = &d;
//is the following ok, or undefined behavior?
B::MethodPtr mp = static_cast<B::MethodPtr>(&D::foo);
(pb->*mp)();
}
Стандарт говорит об этом, говоря о static_cast:
5.2.9.9 An rvalue of type “pointer to member of D of type cv1 T” can be converted to an rvalue of type “pointer to member of B of type cv2 T”, where B is a base class (clause 10) of D, if a valid standard conversion from “pointer to member of B of type T” to “pointer to member of D of type T” exists (4.11), and cv2 is the same cv-qualification as, or greater cv-qualification than, cv1. 63) The null member pointer value (4.11) is converted to the null member pointer value of the destination type. If class B contains the original member, or is a base or derived class of the class containing the original member, the resulting pointer to member points to the original member. Otherwise, the result of the cast is undefined. [Note: although class B need not contain the original member, the dynamic type of the object on which the pointer to member is dereferenced must contain the original member; see 5.5.]
Как всегда, мне очень трудно расшифровать стандарт. Это вроде как говорит, что это нормально, но я не уверен на 100%, действительно ли приведенный выше текст применим к ситуации в моем примере кода.