Он имеет в виду, что объекты в C ++ по своей природе не имеют типов. Хотя вы можете написать
struct Dog {
char* name;
int breed;
};
Dog ralph("Ralph", POODLE);
на самом деле ralph
не имеет типа; это всего лишь куча битов, и процессор не обращает внимания на тот факт, что вы называете эту коллекцию битов Dog
. Например, допустимо следующее:
struct Cat {
int color;
char* country_of_origin;
};
Cat ralph_is_that_you = * (Cat*) &ralph;
С удивлением наблюдайте, как профессор С выполняет трансвидовые мутации между Dog
с и Cat
с! Дело в том, что, поскольку ralph
- это просто последовательность битов, вы можете просто утверждать, что эта последовательность битов действительно является Cat
, и ничто не пойдет не так ... за исключением того, что цвет "Cat
" было бы случайным большим целым числом, и вам лучше не пытаться читать его страну происхождения. Основная проблема заключается в том, что, хотя переменная (например, имя, а не объект, который она представляет) имеет тип, базовый объект - нет.
Сравните это с JAVA, где не только типы, но и объекты имеют внутренние типы. Это может быть отчасти связано с тем, что нет указателей и, следовательно, нет доступа к памяти, но тем не менее существует тот факт, что если вы приведете Dog
к Object
, вы не сможете вернуть его обратно к Cat
, потому что объект знает, что в глубине души это на самом деле Dog
, а не Cat
.
Слабая типизация, присутствующая в C ++, довольно пагубна, поскольку делает статические проверки типов компилятором практически бесполезными, если вы хотите действительно защитить приложение от злоупотреблений, а также затрудняет написание защищенного и надежного программного обеспечения. Например, вам нужно быть очень осторожным, когда вы получаете доступ к «указателю», потому что это может быть любой случайный битовый шаблон.
РЕДАКТИРОВАТЬ 1: Комментарии были очень хорошие моменты, и я хотел бы добавить их здесь.
kts указывает на то, что JAVA от Sun действительно имеет указатели, если вы посмотрите достаточно глубоко. Спасибо! Я не знал, и это довольно круто. Однако фундаментальный момент заключается в том, что объекты JAVA имеют тип , а типы C - нет. Да, вы можете обойти это, но это то же самое, что разница между отказом от рассылки и отказом от рассылки спама: да, вы можете злоупотреблять указателями JAVA, но по умолчанию недопустимо злоупотребление. Вы должны были бы согласиться.
martin-york указывает на то, что приведенный мной пример является чисто C-феноменом. Это правда, но
- C ++ в основном содержит C в качестве подмножества (различия обычно слишком малы, чтобы перечислять).
- C ++ включает
reinterpret_cast<T>
специально для того, чтобы разрешать подобные хаки.
- То, что он обескуражен, не означает, что он не распространен и не опасен. По сути, даже если у JAVA есть дополнительные указатели (как я их назову), дело в том, что человек, использующий их, вероятно, задумался о последствиях. Кастинги Си настолько просты, что иногда они делаются без раздумий (Цитируя Страуструпа, «Но новый синтаксис был сделан намеренно уродливым, потому что приведение все еще уродливо и часто небезопасно».). Есть также тот факт, что работа, необходимая для обхода системы типов JAVA, намного больше, чем то, что могло бы сделать для умного взлома, в то время как обойти систему типов C (и, да, систему типов C ++) достаточно легко, что я видел это сделано только для небольшого повышения производительности.
Во всяком случае, обескураживание чего-либо не делает этого невозможным. Я не одобряю плохое кодирование, но я не видел, чтобы это никуда меня не привело ...
Что касается полезности этой функции, то, по общему признанию, она есть (просто посмотрите «быстрый обратный квадратный корень» в Google или Википедии), но она достаточно опасна, так что, следуя принципу Stroustroup, некрасивые операции должны быть ужасными, порог сложности должен значительно выше.