Это вариант вопросов Downcasting using the Static_cast in C++ и Safety of invalid downcast using static_cast (or reinterpret_cast) for inheritance without added membersбезопасности static_cast указателя к производному классу от базового деструктора
Я не ясно, на фразе в стандарте «В том, что на самом деле подобъекте объекта типа D, полученный указатель указывает на охватывающий объект типа D "относительно поведения в ~ B. Если вы отбрасываете D в ~ B, это все еще подобъект в этой точке? Следующий простой пример показывает, вопрос:
void f(B* b);
class B {
public:
B() {}
~B() { f(this); }
};
class D : public B { public: D() {} };
std::set<D*> ds;
void f(B* b) {
D* d = static_cast<D*>(b); // UB or subobject of type D?
ds.erase(d);
}
Я знаю, что литая открытая дверь к катастрофе, и делать что-нибудь подобное из dtor это плохая идея, но КОЛЛЕГА претензий «Код действителен и работает корректно. Это отличное исполнение. В комментарии четко сказано, что его нельзя разыменовать ».
Я указал, что бросок не нужен, и мы должны предпочесть защиту, предоставляемую системой типов, комментариям. Печальная часть состоит в том, что он является одним из старших/ведущих разработчиков и предполагаемым C++ «экспертом».
Могу я сказать ему, что актер - UB?
Я _think_ это UB, но я не уверен. Тем не менее, код [по крайней мере, в этом примере] абсолютно пахнет хуже моих носков после двух недель в жаркое лето без мытья ... Правильная вещь здесь была бы иметь дескриптор в 'D', который удалял объект из' ds' - это не должно быть сделано в 'B'. Это, конечно же, также позволит избежать проблем с UB. Тот факт, что он действительно может работать и хорошо определен, не имеет значения. Или сделайте 'ds' в' std :: set bs' ... –
До тех пор, пока не существует других классов, полученных из B и D, не имеет дополнительных членов, это может сработать. Но все это пахнет. Как вы можете убедиться, что каждый B - это D, и если это точно, почему у вас будут разные классы в первую очередь? –
@MatsPetersson: Почему вы думаете, что это UB? Стандарт в 5.2.9 дает пример, почти равный OP, хотя он использует ссылки: 'struct B {}; struct D: public B {}; D d; B & br = d; static_cast(br); 'Конечно, это только теоретический вопрос. Код в вопросе OP ужасен. –