简体   繁体   中英

C++ const_cast over a dynamic_cast and vice versa

I have a doubt about about a line of the code wrote from my professor.

This is the full code.

The relevant function is

std::vector<AbstractButton*> removeUnchecked() {
    std::vector<AbstractButton*> v;
    CheckBox* p;
    for(auto it = Buttons.begin(); it != Buttons.end(); ++it) {
      p = const_cast<CheckBox*>(dynamic_cast<const CheckBox*>(*it));
      if(p && !(p->isChecked())) {
    v.push_back(p);
    it = Buttons.erase(it); --it;
      }
    }
    return v;
  }

The class Gui has a std::list<const AbstractButton*> Buttons and the function std::vector<AbstractButton*> removeUnchecked(){} wants a vector as return type and we had to remove from the Gui every checkable buttons with the attribute checked == false and put it in the returned vector.

The professor wrote CheckBox* p = const_cast<CheckBox*>(dynamic_cast<const CheckBox*>(*it)); performing a dynamic_cast first and then a const_cast

If I had written CheckBox* p = dynamic_cast<CheckBox*>(const_cast<AbstractButton*>(*it)) would it be the same thing? ( const_cast first and then dynamic_cast )

Both orders of the cast should be fine and do the same thing.

const_cast will return a pointer pointing to the same object as before or a null pointer value if the argument is a null pointer value.

dynamic_cast either returns a pointer pointing to a CheckBox object or a null pointer value, without depending on the const , except that it refuses to cast away a const .


From looking at just the code you linked, it isn't clear to me though why the objects are stored as const pointers in the first place.

const_cast is one of the more dangerous casts. You must guarantee that the pointer which you const_cast doesn't actually point to an object with const type. If it does, then trying to modify the object through the new non- const pointer will cause undefined behavior.


However in the code in your link there is an unrelated bug in the function. It uses std::list::erase to remove the elements while iterating over the list. It correctly uses the return value of std::list::erase as a new iterator to the next element.

But then, because the for loop always executes it++ , in the loop body you it-- the return value from std::list::erase to compensate.

However, if you just removed the first element of the list, then std::list::erase will return a pointer to the new first element of the list, ie the new .begin() iterator. Decrementing this pointer is not allowed and causes undefined behavior.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM