static_cast родительского класса в дочерний класс С++

Результатом этой программы является «Метод B». Как экземпляр родительского объекта может вызвать функцию дочернего класса через static_cast?

Чтобы еще больше запутать ситуацию, если я сделаю метод() виртуальным, то этот код выведет «Метод А».

Кто-нибудь может объяснить, что здесь происходит?

class A {
public:

    void method() {
        cout << "Method A" << endl;
    }

};

class B : public A {
public:
    void method() {
        cout << "Method B" << endl;
    }
};

int main() {
    A a;
    B* bptr = static_cast<B*>(&a);
    bptr->method();
}

person Dante    schedule 15.04.2016    source источник
comment
Это неопределенное поведение. Вам просто повезло, что cout << "Method B" << endl; не имеет значительных побочных эффектов.   -  person πάντα ῥεῖ    schedule 15.04.2016
comment
Понижение от родительского объекта к дочернему объекту всегда является неопределенным поведением? Я правильно понимаю?   -  person Dante    schedule 15.04.2016
comment
Вы можете сделать это безопасно, используя либо CRTP, либо dynamic_cast.   -  person πάντα ῥεῖ    schedule 15.04.2016
comment
@ Данте Конечно. Родитель — это не ребенок, поэтому попытка сделать родителя дочерним — это UB.   -  person NathanOliver    schedule 15.04.2016
comment
Вы должны использовать dynamic_cast для понижения   -  person Nacho    schedule 15.04.2016
comment
B b; A* aptr = dynamic_cast<A*>(&b); aptr->method(); Кроме того, почему этот метод вывода также выводит B? Как преобразовать родительский указатель в дочерний объект, чтобы я мог вызывать родительский метод вместо дочерних?   -  person Dante    schedule 15.04.2016
comment
Я думаю, у вас могут быть неправильные определения, прочитайте это для уточнения   -  person Nacho    schedule 15.04.2016
comment
@Dante Вы должны проверить результаты dynamic_cast. Причина, по которой это работает, та же, что и в моем вступительном комментарии.   -  person πάντα ῥεῖ    schedule 15.04.2016
comment
Вы можете использовать статическое приведение для понижения приведения, если у вас есть гарантия, что фактический тип объекта является дочерним (это то, что делает CRTP). В противном случае это неопределенное поведение.   -  person SergeyA    schedule 15.04.2016
comment
@Dante, случается, что он работает и выводит метод B, потому что B::method ни к чему не обращается, это может быть и бесплатная функция. Создайте член в B и попробуйте что-нибудь сделать с ним в B::method. Поскольку a не B, вы, вероятно, взорветесь.   -  person David    schedule 15.04.2016
comment
@Nacho На самом деле для понижения (от базы к производной) лучше использовать static_cast: stackoverflow.com/q/32506579/2642059 Очевидно для этого требуется, чтобы программист разработал код, чтобы приведение было законным ... чего здесь, конечно, не было сделано.   -  person Jonathan Mee    schedule 15.04.2016
comment
Спасибо за ответы всем. Это был просто эксперимент для меня, чтобы попытаться выяснить, как правильно забрасывать и какие существуют возможные способы заброса, я думаю, что теперь у меня есть лучшее понимание.   -  person Dante    schedule 15.04.2016