Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Книги с которыми мы не согласны  (Прочитано 7105 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« : 21-03-2007 08:05 » 

Добрый день, Сообщество!

Читал я на досуге Алена Голуба
"ВЕРЕВКА ДОСТАТОЧНОЙ ДЛИНЫ, ЧТОБЫ… ВЫСТРЕЛИТЬ СЕБЕ В НОГУ
Правила программирования на Си и Си++"

Не согласен со следующими правилами Улыбаюсь

137. Виртуальная функция не является виртуальной, если вызывается из конструктора или деструктора

Ну на самом деле(насколько мне известно Улыбаюсь ) при вызове виртуальных функций класса из нутри класса не используется механиз виртуализации за исключением случая когда функция не переопределена в потомке, кроме того использование механизма виртуализации не обязательно при вызове функций объекта созданного на стеке при обращении к нему по имени, а не указатель на базовый класс.

Цитата
   138. Не вызывайте чисто виртуальные функции из конструкторов
   Это правило вытекает из только что рассмотренной картины. Определение "чисто" виртуальной функции (у которой =0 вместо тела) приводит к тому, что в таблицу виртуальных функций базового класса помещается NULL вместо обычного указателя на функцию. (В случае "чисто" виртуальной функции нет функции, на которую необходимо указывать). Если вы вызываете чисто виртуальную функцию из конструктора, то используете таблицу базового класса и на самом деле вызываете функцию при помощи указателя NULL. Вы получите дамп оперативной памяти на машине с UNIX и "Общая ошибка защиты" в системе Windows, но MS-DOS просто исполнит то, что вы просили, и попытается выполнить код по адресу 0, считая его правильным.

Ха Улыбаюсь. Кто сказал что у чисто виртуальной функции не может быть тела?
Вызывайте смело, если есть тело функции.

В подтверждение вот код:
Код:
class Base
{
public:
Base();
void virtual print() = 0;
};

Base::Base()
{
print();
}
void Base::print()
{
std::cout << "Base::print()\n";
}

class Deliver:public Base
{
public:
Deliver(){print();}
void virtual print();

};

void Deliver::print()
{
std::cout << "Deliver::print()\n";
}


int _tmain(int argc, _TCHAR* argv[])
{
Deliver d;
d.print();
dynamic_cast<Deliver*>(&d)->print();
dynamic_cast<Base*>(&d)->print();
return 0;
}

и ассемблерный код:
Код:
d.print();
00412816  lea         ecx,[d]
00412819  call        Deliver::print (411023h)
dynamic_cast<Deliver*>(&d)->print();
0041281E  lea         ecx,[d]
00412821  call        Deliver::print (411023h)
dynamic_cast<Base*>(&d)->print();
00412826  mov         esi,esp
00412828  mov         eax,dword ptr [d]
0041282B  lea         ecx,[d]
0041282E  call        dword ptr [eax]
00412830  cmp         esi,esp
00412832  call        @ILT+235(__RTC_CheckEsp) (4110F0h)
return 0;
00412837  xor         eax,eax

далее
Цитата
   145. Операция — это сокращение (без сюрпризов)
   .........
   .........
   .........
   Другим хорошим примером того, как нельзя действовать, является интерфейс Си++ iostream. Использование сдвига (<<) для обозначения "вывод" является нелепым. Ваши функции вывода в Си назывались printf(), а не shiftf(). Я понимаю, что Страуструп выбрал сдвиг, потому что он сходен с механизмом перенаправления ввода/вывода различных оболочек UNIX, но этот довод на самом деле не выдерживает проверки. Страуструп исходил из того, что все программисты на Си++ понимают перенаправление в стиле UNIX, но эта концепция отсутствует в некоторых операционных системах — например, в Microsoft Windows.
   .........
   .........
   .........

Последнее предложение ставит меня в тупик. Я довольно часто по виндой использую перенаправление потоков и pipe при работе в командной строке, МС ДОС помниться тоже поддерживал эту штуку.

Цитата
   .........
К тому же, для того, чтобы аналогия была полной, операция > должна быть перегружена для выполнения операции затирания, а >> — добавления в конец. Тем не менее, тот факт, что > и >> имеют различный приоритет, делает реализацию такого поведения затруднительной. Дело осложняется тем, что операторы сдвига имеют неправильный уровень приоритета. Оператор типа cout << x += 1 не будет работать так, как вы ожидаете, потому что у << более высокий приоритет, чем у +=, поэтому оператор интерпретируется как (cout << x) += 1, что неверно. Си++ нуждается в расширяемости, обеспечиваемой системой iostream, но он вынужден добиваться ее за счет введения операторов "ввода" и "вывода", имеющих низший приоритет по отношению к любому оператору языка.
   .........

Ну так-то оно так, но будет ошибка компиляции, что не так страшно обернул скобками и работай дальше.

Цитата
   .........
   Аналогия проблеме "сдвиг как вывод" может быть найдена в проектировании компьютерных систем. Большинство проектировщиков аппаратуры были бы счастливы использовать + вместо OR, а * вместо AND, потому что такая запись используется во многих системах проектирования электронных компонентов. Несмотря на это, перегрузка операции operator+() в качестве OR явно не нужна в Си++. К тому же, лексема << означает "сдвиг" в Си и Си++; она не означает "вывод".
   .........

лично для мне перегруженные <<  и >> интуитивно понятны.

Цитата
   Как завершающий пример этой проблемы — я иногда видел реализации класса "множество", определяющие | и & со значениями "объединение" и "пересечение". Это может иметь смысл для математика, знакомого с таким стилем записи, но при этом не является выражением ни Си, ни Си++, поэтому будет незнакомо для вашего среднего программиста на Си++ (и вследствие этого с трудом сопровождаться). Амперсанд является сокращением для AND; вы не должны назначать ему произвольное значение. Нет абсолютно ничего плохого в a.Union(b) или a.intersect(b). (Вы не можете использовать a.union(b) со строчной буквой u, потому что union является ключевым словом).

выше капец, то не используй это не используй, лично меня перегруженные операторы & в BOOST::SERIALIZE вполне устраивают. Кроме того перегрузка поператор даёт возможность написать

ar & a & b & c;
а не городить огород из
ar.Union(a);
ar.Union(b);
ar.Union(c);
особенно это относится к <<

Вот высказал своё ИМХО, критикуйте Улыбаюсь
Записан

Странно всё это....
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #1 : 21-03-2007 08:09 » 

еще одно:
   148. Перегруженные операции должны работать точно так же, как они работают в Си

Ну пишем мы на C++, человек не обязан знать C если пишет на C++ и тем более под него подстраиваться.
Записан

Странно всё это....
Anchorite
Гость
« Ответ #2 : 21-03-2007 13:06 » 

LogRus я с тобой согласен.

В конце-концов можно и комментариев написать, что делает данная функция или оператор.
Записан
Scorp__)
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 21-03-2007 15:03 » new

LogRus, тоже абсолютно согласен. Вообще концепция "пусть неудобно, зато правила соблюдаются" меня не очень привлекает, тем более когда правила не обязательны, а просто тащат за собой какие-то старые догмы.

Тем более неправильно жестко ограничивать именно область перегрузки операторов, на мой взгляд тут лучше руководствоваться лишь здравым смыслом. А то, так и умные указатели можно в преступников записать, у некоторых селектор -> совсем не так работает как в С.
Записан

- А Вы сами-то верите в привидения?
- Конечно, нет, - ответил лектор и медленно растаял в воздухе.
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines