- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 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.05.2014 16:00 # 0
bormand 29.05.2014 16:07 # 0
15 - заменяет один мусор в поле a на другой (VMT не перетрется, т.к. это просто сгенеренный компилером оператор присваивания)
16 - теперь там объект типа B с a = 5 и b = 2
17 - нормально раскастовывается в B
18 - выводит 2 и 5
Как-то так?
absolut 29.05.2014 16:12 # 0
Кто попросил? Тут вроде как всё очевидно. Несмотря на излишества.
someone 29.05.2014 16:36 # 0
absolut 29.05.2014 16:39 # 0
bormand 29.05.2014 16:39 # +1
А что там смущает? Там сгенеренный оператор присваивания класса А родитель это, по сути, просто поле в дочернем классе.
absolut 29.05.2014 16:52 # 0
имя функции Вообще, да, обычное почленное копирование. Но перезаписывать базовую часть производного класса не есть гуд, ибо инвариант может быть нарушен.
roman-kashitsyn 29.05.2014 16:56 # +2
absolut 30.05.2014 11:02 # +1
bormand 29.05.2014 16:59 # +1
Так он в паблике висит. От этого и проблемы с инвариантами. А оператор присваивания ничем не виноват. Даже если бы его не было - останутся все остальные методы базового класса, которые никто не запретил вызывать.
guest 31.05.2014 10:40 # +1
Код совершенно валидный.
То есть, здесь нет никакого 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
bormand 31.05.2014 10:50 # 0