1. C++ / Говнокод #16076

    +5

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    struct A {
      int a;
      virtual ~A() {}
    };
    struct B: public A {
      int b;
      B(int _b):b(_b){}
      virtual ~B() {}
    };
    A func(){return A();}
     
    int main(int argc, char* argv[])
    {
      A* a = new B(2);  
      *a = func();
      a->a = 5;
      B *b = dynamic_cast<B*>(a);
      std::cout << b->b << "\t" << b->a;
      return 0;
    }

    Меня попросили ответить что выведет на экран.

    Запостил: laMer007, 29 Мая 2014

    Комментарии (12) RSS

    • Ответить
    • 14 - a указывает на объект типа B с неопределенным a и b = 2
      15 - заменяет один мусор в поле a на другой (VMT не перетрется, т.к. это просто сгенеренный компилером оператор присваивания)
      16 - теперь там объект типа B с a = 5 и b = 2
      17 - нормально раскастовывается в B
      18 - выводит 2 и 5

      Как-то так?
      Ответить
    • >Меня попросили ответить что выведет на экран.
      Кто попросил? Тут вроде как всё очевидно. Несмотря на излишества.
      Ответить
    • Это просто обязано быть UB.
      Ответить
      • в каком месте? единственное что смущает, это 15 строка.
        Ответить
        • > единственное что смущает, это 15 строка
          А что там смущает? Там сгенеренный оператор присваивания класса А родитель это, по сути, просто поле в дочернем классе.
          Ответить
          • >А что там смущает?
            имя функции Вообще, да, обычное почленное копирование. Но перезаписывать базовую часть производного класса не есть гуд, ибо инвариант может быть нарушен.
            Ответить
            • Наложение дополнительных инвариантов на базовый класс нарушает принцип подстановки.
              Ответить
            • > ибо инвариант может быть нарушен
              Так он в паблике висит. От этого и проблемы с инвариантами. А оператор присваивания ничем не виноват. Даже если бы его не было - останутся все остальные методы базового класса, которые никто не запретил вызывать.
              Ответить
    • ответ 2 и 5.
      Код совершенно валидный.
      То есть, здесь нет никакого UB

      A* a = new B(2); //a=мусор, b=2
      *a = func(); //a.A::operator=( A() ) ---> a=мусор, b=2
      a->a = 5; //a=5, b=2

      B *b = dynamic_cast<B*>(a); //каст правомерен
      std::cout << b->b << "\t" << b->a; //вывод: 2 5
      Ответить

    Добавить комментарий