Предлагаю взглянуть на улыбку Чеширского кота - прием в программировании, применяющийся для сокрытия информации из распространяемых с библиотекой h-ников. Он нацелен на то, чтобы после попадания h-ника в агрессивную среду, прикладные программисты не обращались к закрытым методам и полям через указатели. Предполагается,что дизасмы использоваться не будут, только уровень сишняка. Итак: Код (Text): //Secret.h class Secret { private: struct Cheshire; // Class declaration only Cheshire* smile; // Cheshire smile:) public: Secret(); ~Secret(void){delete smile;} int read(); void change(int); }; //Secret.cpp #include "Secret.h" struct Secret::Cheshire { int i; //Other secret variables....... void initialize_var() {i=0;} int read_var(){return (i);} void set_var(int j) {i=j;} //Other secret functions....... }; Secret::Secret() { smile = new Cheshire; smile->initialize_var(); } int Secret::read() { return(smile->read_var()); } void Secret::change(int x) { smile->set_var(x); } Как видно в h-нике лишь определены открытые функции-обертки и указатель на секретную структуру Cheshire (в которой определены реальные функции и поля). Реализация библиотеки распространяется в объектном файле и из исходников программисту доступен лишь h-ник. При попытки создания объекта структуры Cheshire - улыбается Чеширский кот (вылетит ошибка), то есть создать можно лишь указатель и прикладной программист не может получить информацию о внутренних данных и методах секретной структуры.
asd Ну что сказать - насчет отзыва на книгу Страуструпа частично согласен. Герберт Шилдт тоже пишет справочники, хоть он и не создатель языка С++, но он описывает возможности языка последовательно, интересно и главное понятно. Не знаю какую надо иметь силу воли, чтоб дочитать сухие заумные изречения Страуструпа до конца.
а мне нравится читать его спец издание язык программирования с++ > 1000 страниц еще дизайн и эволюция интересная часто заглядываеш как в справочник в них
Nafanya, вообще-то это называется pImpl. Да и вообще, смысл писать очевидные вещи, известные любому более-менее серьезному программисту C/C++. Лучше иди почитай Саттера и Мэйерса.
Пока тему не прикрыли, хотел бы узнать: как лучше (эффективнее) использовать fread? Так: Код (Text): fread(&header, sizeof(BITMAPFILEHEADER), 1, stream); Или так: Код (Text): fread(&header, 1, sizeof(BITMAPFILEHEADER), stream);
по большому счету разницы нет... в винде лучше наверное так: Код (Text): fread(&header, sizeof(BITMAPFILEHEADER), 1, stream); так как это одна итерация ReadFile... подробности в исходниках CRT...
В книге "Философия Си++" Брюса Эккеля (1-ый том 376 страница) в пункте об вложенном итераторе на мой взгляд косяк. Оригинал кода: Код (Text): bool operator++() { // Prefix if(index >= oc.a.size()) return false; if(oc.a[++index] == 0) return false; return true; } Если индекс в векторе равен (Size-1), где Size размер вектора, то при вызове функции инкремента код if(index >= oc.a.size()) return false; не вернет false. При выполнении следующей строки кода if(oc.a[++index] == 0) return false; налицо вылет за границы вектора!
опять же по-моему все именно так, как и должно быть))) хотя для надежности надо было бы ставить постфиксный инкремент, чтобы уж наверняка))) вам наверное интересно будет прочесть: http://lurkmore.ru/++i_+_++i
Rel Префикс и постфикс - две большие разницы. С префиксом там действительно косяк, ибо брать значение по size незя.
блин... это шутка, вы видите много скобочек в конце предложений?)) это смайлики))) на самом деле понятно, что префиксный инкремент выполниться первым, но смотрите... это перегруженный оператор класса... реализация может быть любой... вполне возможно, что в операторе реализована проверка выхода за границу и возврат нуля в случае неудачи... то есть ++index является проверкой на следующий элемент... или вполне возможно, что итерация начинается с единицы, а не с нуля... все может быть, надо смотреть реализацию класса...
Rel Одних смайликов недостаточно для шутки. Вот тут я вообще не понял, оператор ++ вызвать можно? Можно, и значит выйти за границы массива тоже можно.
оператор ++ относится к индексу, мне всетки кажется, что индекс - не класс)) "все может быть" относилось к реализации oc.a и к перегрузке оператора []... давайте посмотрим на эту проблему с другой стороны... предположим, что "вектор", о котором говорится в примере (он же oc.a) - это std::vector из stl... мы делаем для него итератор... вспомним, что возвращает функция std::vector::end()... она возвращает итератор, указывающий за последний элемент вектора... то есть итератор при инкременте должен увеличивать индекс до тех пор, пока индекс не станет равным размеру... может быть с этим связано... проверка на ноль канеш выглядит довольно странно для "не строки"... а так канеш надо книгу смотреть, каждый из авторов может ошибиться... просто не надо думать, что книги пишут программисты уровня Нафани)))
Rel Разыменовывать такой итератор всё равно нельзя. Однозначный фейл. И вообще итераторы здесь абсолютно не причём, их здесь просто нет, тупо обращение к элементу за границами массива. С другой стороны удивляться ошибкам в книгах не стоит, они очень часты.
Rel oc.a стандартный вектор. Выкладываю оригинал кода из книги целиком. Посмотрите как реализован итератор, там действительно вылет за границы вектора. (SmartPointer::operator++())