Почему std:: sub match публично наследуется от std:: pair?
Я читал документацию std::sub_match<BidirectionalIterator> и увидел, что он публично наследует от std::pair<BidirectionalIterator, BidirectionalIterator>. Сsub_match - это просто пара итераторов в последовательности символов, с некоторыми дополнительными функциями, я могу понять, что он реализован с помощью pair, но зачем использовать открытое наследование?
проблема с наследованием публично от std::pair<T,U> это то же самое, что и наследование публично от большинства других стандартных классов: они не предназначены для полиморфного манипулирования (в частности, они не определяют виртуальный деструктор). Другие члены также не будут работать должным образом, а именно оператор присваивания и функция-член swap (они не будут копировать matched член sub_match).
Почему разработчики Boost, а затем комитет решил реализовать sub_match публично наследовать от pair вместо использования композиции (или частного наследования с использованием деклараций, если они хотели сохранить доступ к членам через first и second)?
5 ответов
это интересный вопрос. Предположительно, они считали это безопасным
потому что никто никогда не будет динамически распределять их в любом случае. Об
единственный способ получить sub_match objects является возвращаемым значением
из некоторых функций basic_regex, или копии иных
sub_match, и все они будут либо временными, либо локальными
переменная.
обратите внимание, что это не безопасно держать sub_match объекты вокруг в любом случае, так как
они содержат итераторы, срок службы которых... не кажется указано в
стандарт. Пока
потому что C++ не может наследовать интерфейс без публичного наследования. Вы можете наследовать реализацию с частным наследованием, но тогда все является частным. Если вы хотите тот же интерфейс, что и std::pair вы должны быть a std::pair.
кроме того, рассмотрим это. Это, очевидно, неопределенное поведение:
std::sub_match<BidirectionalIterator> theMatch = ...;
std::pair<BidirectionalIterator> *pMatch = &theMatch;
delete pMatch;
но вот это:
std::sub_match<BidirectionalIterator> theMatch = ...;
std::pair<BidirectionalIterator> *pMatch = &theMatch.pair;
delete pMatch;
почему первый из них гораздо больше беспокоит, чем второй?
sub_match и pair являются легкими объектами (в зависимости от их содержания, конечно). Они предназначены для копирования или передачи по ссылке, все из которых на 100% безопасны. Существует мало, если есть какая-либо причина, чтобы выделить их в куче и использовать их через указатели. Поэтому, хотя я понимаю вашу озабоченность, я думаю, что это вряд ли произойдет в любом реальном коде.
вот что regexавтор должен сказать об этом: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1429.htm#matches_discussion
боюсь, ничего особенного в вашем вопросе.
Я бы предположил, что это решение было компромиссом между изобретением колеса и введением небольшого риска неправильного использования. Обратите внимание, что в общем случае нет необходимости создавать sub_match они возвращались из . Сверх того пары итераторы - очень практичный способ реализации диапазонов.
Если std::sub_match<BidirectionalIterator> не имеет собственного состояния, тогда это нормально для него наследовать от std::pair. Только не дома.