In C++ primer(5th) 19.2.1 about dynamic_cast. It says, for dynamic_cast to be successful,
the type of e must be either a cla
The type of pb is indeed a public base class of D, but the object that pb points to is not the base subobject of any object of type D. The dynamic cast detects this and returns null.
If indeed you did attempt to cast the pointer to a base subobject of a D object, you would get the (non-null) pointer to the D object:
D obj;
B *pb = &obj; // points at subobject
assert(&obj == dynamic_cast(pb));
The requirement that you've cited is merely a static requirement that allows you to use the dynamic cast at all -- but it does not describe the result of using the cast. That's described later on.