Как лучше передать функции двумерный массив?
Как лучше передать функции двумерный массив?
Лучше всего иметь свой соотв. тип для такого массива
typedef std::vector< std::vector<int> > TIntDblArray;
или т.п., или даже класс-обертку.
А передавать как обычно: указатель, ссылку, копию.
Как лучше передать функции двумерный массив?
Можешь передать в виде void или char указателя. Дешево и сердито.
Можешь передать в виде void или char указателя. Дешево и сердито.
Это плохой тон и неправильно с точки зрения типовой безопасности.
Это плохой тон и неправильно с точки зрения типовой безопасности.
Тон на самом деле хороший - главное сделать все правильно. Любой многомерный массив в любом случае представляет из себя линейный дамп памяти - и никуда от этого не денешься. Так что какая разница кто будет перемножать строки на столбцы - ты или компилятор? Результат - один и тот-же. К тому же, как показывает практика - вариант с линейным массивом - однозначно надежне.
Так что позволь в этом вопросе с тобой не согласиться.
Тон на самом деле хороший - главное сделать все правильно. Любой многомерный массив в любом случае представляет из себя линейный дамп памяти - и никуда от этого не денешься. Так что какая разница кто будет перемножать строки на столбцы - ты или компилятор? Результат - один и тот-же. К тому же, как показывает практика - вариант с линейным массивом - однозначно надежне.
Так что позволь в этом вопросе с тобой не согласиться.
Ты видишь разницу между Ассемблером, C и C++ ?
В отличии от первых двух C++ является языком высокого уровня, и в него основу заложено такое понятие, как "Типовая безопасность". В связи с этим были введены static_cast, dynamic_cast, reinterpret_cast.
Если я тебя не могу убедить, может, Страуструп убедит? "Язык программирования С++. Специальное издание", п.6.2.7 или п.6.5 совет 4 и 5.
Если нужны примеры несостоятельности твоего предложения с void*, могу привести.
Ты видишь разницу между Ассемблером, C и C++ ?
В отличии от первых двух C++ является языком высокого уровня, и в него основу заложено такое понятие, как "Типовая безопасность". В связи с этим были введены static_cast, dynamic_cast, reinterpret_cast.
Если я тебя не могу убедить, может, Страуструп убедит? "Язык программирования С++. Специальное издание", п.6.2.7 или п.6.5 совет 4 и 5.
Если нужны примеры несостоятельности твоего предложения с void*, могу привести.
Любопытно будет посмотреть чего такого "несостоятельного" может быть.
Касаемо асма - в любом случае передача параметра будет выглядеть как
push <ptr to array>
ну или mov eax, <ptr to array>
в зависимости от типа вызова.
По поводу тайп кастов...
Мысль конечно интересная - но объясни к примеру тогда такой момент:
для каждого переобъявляемого типа ты, к примеру будешь писать враппер того-же memset-a или memcpy?
А передача-то параметров идет как-раз через void указатель.
К тому-же, что тебе мешает после приема параметра функцией воспользоваться преобразованием void указателя к нужному тебе типу? Задачка-то элементарная - для первого класса.
К тому же:
к примеру что мешает сделать определение следующего рода: typedef int _new_type[4][4];?
Причем данный вариант тоже работает, как ни странно.
Ссылаться на Страуструпа хорошо - но ты не исключаешь такой возможности что подходы к решению одной и той-же проблемы могут оказаться разными, но вместе с тем правильными?
Приведу пример:
Пример реальный - взят из исходников одного японца:
=========================
char *mem;
int offset=0;
BYTE read_byte(void)
{
BYTE result=mem[offset];
offset++;
return result;
}
DWORD read_dword(void)
{
DWORD result;
BYTE b1,b2,b3,b4;
b1=read_byte();
b2=read_byte();
b3=read_byte();
b4=read_byte();
result=b1+b2*0x100+b3*0x10000+b4*0x1000000;
return result;
}
=========================
А вот второй вариант реализации:
BYTE read_byte(void){return mem[offset++];}
DWORD read_dword(void)
{
offset+=4;
return *(DWORD*)(mem+offset-4);
}
=========================
О различиях судите сами.
И нельзя сказать что какой-то из этих двух фрагментов написан неправильно с точки зрения работоспособности. Оба делают одни и те же вещи, только по разному.
И извини меня - с динамической памятью работаю уже далеко не первый год так что могу сказать следующее:
Никаких проблем с "Типовой безопасностью" никогда не возникало. И ни у кого не возникнет - ежели руки к тому месту приделаны. А если не к тому - то никакая "Типовая безопасность" в таком случае не спасет.
Лично я кодом мусорить не люблю. Кому и как писать каждую конкретную задачу - это его личное дело. А плохой это тон или не плохой - это уже мнение субъективное, а не объективное.
Вообще-то, если на то пошло, в языках высокого уровня предусмотрен такой оператор как GOTO.
Им можно пользоваться - но почему-то его применяют редко, потому что это тоже считается плохим тоном, тем более что без него можно прекрасно обойтись.
А я всего-лишь посоветовал человеку, как можно решить его проблему, с моей точки зрения с минимумом геморроя. Если захочет - может воспользоваться моим советом - не захочет воспользуется твоим или еще чьим нибудь.
В конце-концов думать надо иногда и самому - тогда можно додуматься до того, до чего мог не додуматься дядя Страуструп.
Любопытно будет посмотреть чего такого "несостоятельного" может быть.
Пример ошибки из-за использования void*
{
.....
}
void func(void* p)
{
B* pB = (B*)p;
.....
}
int main()
{
C c;
func(&c);
.....
}
Касаемо асма - в любом случае передача параметра будет выглядеть как
Ну ты же не асме пишешь, а на С++
для каждого переобъявляемого типа ты, к примеру будешь писать враппер того-же memset-a или memcpy?
А передача-то параметров идет как-раз через void указатель.
"переобъявляемого" - это как?
Я необязательно буду писать враппер, точнее правильнее будет никогда не использовать memset и memcpy для инициализации и копирования экземпляров класса. Хотя иногда для быстроты приходиться, но это иногда опасная быстрота.
memcpy и memset - это "пережитки прошлого", а именно С, которые иногда доставляют неудобство.
К тому-же, что тебе мешает после приема параметра функцией воспользоваться преобразованием void указателя к нужному тебе типу? Задачка-то элементарная - для первого класса.
Для первого класса? Смотри пример выше.
К тому же:
к примеру что мешает сделать определение следующего рода: typedef int _new_type[4][4];?
Причем данный вариант тоже работает, как ни странно.
Ну это и есть моё предложение, если ты читал мой первый пост. Вектора я привел для примера, т.к. считаю, что такой механизм гибче и безопаснее, чем [][].
Ссылаться на Страуструпа хорошо - но ты не исключаешь такой возможности что подходы к решению одной и той-же проблемы могут оказаться разными, но вместе с тем правильными?
Не исключаю, но использование void* в С++ это некорректный подход
Приведу пример:
Пример реальный - взят из исходников одного японца:
=========================
char *mem;
int offset=0;
BYTE read_byte(void)
{
BYTE result=mem[offset];
offset++;
return result;
}
DWORD read_dword(void)
{
DWORD result;
BYTE b1,b2,b3,b4;
b1=read_byte();
b2=read_byte();
b3=read_byte();
b4=read_byte();
result=b1+b2*0x100+b3*0x10000+b4*0x1000000;
return result;
}
=========================
А вот второй вариант реализации:
BYTE read_byte(void){return mem[offset++];}
DWORD read_dword(void)
{
offset+=4;
return *(DWORD*)(mem+offset-4);
}
=========================
О различиях судите сами.
И нельзя сказать что какой-то из этих двух фрагментов написан неправильно с точки зрения работоспособности. Оба делают одни и те же вещи, только по разному.
Это, скорее C, чем C++.
Оба примера считаю бестолковыми и потенциально ошибочными:
1) использование глобальных переменных, обычно такие вещи оборачивают в класс;
2) если требуется обеспечить считывание без потери информации, то никто не гарантирует, что размер BYTE один байт, а DWORD четыре байта, тут надо использовать sizeof;
Могу предложить такой вариант:
T read()
{
T val = *(T*)(mem+offset);
offset += sizeof T;
return val;
}
только желательно, как метод класса.
И извини меня - с динамической памятью работаю уже далеко не первый год так что могу сказать следующее:
Что есть "динамическая память"? DRAM?
Какая бывает еще?
Почему постоянно пытаются давить авторитетом: "работаю уже далеко не первый год", "c ЯУЗа начинал" и т.п.
Никаких проблем с "Типовой безопасностью" никогда не возникало.
А должно было, судя по технике. Просто, видимо, мало работал с C++.
И ни у кого не возникнет - ежели руки к тому месту приделаны. А если не к тому - то никакая "Типовая безопасность" в таком случае не спасет.
Какое примитивный взгляд...
А для чего акробатам страховка? У них то вроде ноги к тому месту приделаны?
А плохой это тон или не плохой - это уже мнение субъективное, а не объективное.
Если пишешь для себя, на коленках...
А если серьезный коммандный проект, то это не просто плохой тон, а скрытая диверсия.
Вообще-то, если на то пошло, в языках высокого уровня предусмотрен такой оператор как GOTO.
Не во всех.
Им можно пользоваться - но почему-то его применяют редко, потому что это тоже считается плохим тоном, тем более что без него можно прекрасно обойтись.
Ага... и без void* можно и нужно обходиться
А я всего-лишь посоветовал человеку, как можно решить его проблему, с моей точки зрения с минимумом геморроя.
Минимум геморроя? Человек учиться, вырабатывает технику. Знаешь, сколько у него потом уйдет времени для валавливания бага, приведенного мной в начале поста?
В конце-концов думать надо иногда и самому - тогда можно додуматься до того, до чего мог не додуматься дядя Страуструп.
Без слов...
Пример ошибки из-за использования void*
{
.....
}
void func(void* p)
{
B* pB = (B*)p;
.....
}
int main()
{
C c;
func(&c);
.....
}
Смеялся долго. Оставлю сей опус без комментариев...
Если тебя так волнует данный аспект - могу посоветовать следующее - когда пишешь код, внимательнее смотри за тем ЧЕГО и КУДА передаешь. Так глядишь и проги корректнее работать будут.
Ну ты же не асме пишешь, а на С++
А чего в результате получаем? Ты еще скажи скрипты на вижуал бейсике.
Я необязательно буду писать враппер, точнее правильнее будет никогда не использовать memset и memcpy для инициализации и копирования экземпляров класса.
Сабжект посмотри - человек вообще спрашивал о том как передавать в функцию двумерный массив. Я например не вижу никакой аналогии между массивом и классом.
memcpy и memset - это "пережитки прошлого", а именно С, которые иногда доставляют неудобство.
Может ты еще скажешь что весь STL пережиток прошлого? Может его и юзать ненадо? А чем ты собсно данные копировать будешь? Может ReadFile-ом или еще того круче в цикле for???
А C++ чем по-твоему от C отличается?
Это, скорее C, чем C++.
Оба примера считаю бестолковыми и потенциально ошибочными:
1) использование глобальных переменных, обычно такие вещи оборачивают в класс;
Просто супер!
А ежели я так напишу:
class reader
{
private:
char *mem;
public:
BYTE read_byte(void);
DWORD read_dword(void);
};
BYTE reader::read_byte(void)
{
return mem[offset++];
}
DWORD reader::read_dword(void)
{
offset+=4;
return *(DWORD*)(mem+offset-4);
}
Тебе не кажется что это те-же яйца только в профиль? Или скажешь что я с классами работать не умею?
2) если требуется обеспечить считывание без потери информации, то никто не гарантирует, что размер BYTE один байт, а DWORD четыре байта, тут надо использовать sizeof;
Ну это ты вообще отмочил!
Если мне надо прочитать 1 байт а sizeof мне вернет 4 - тебе не кажется что это будет для меня совсем неподходящим вариантом.
BYTE он потому и байт что 1, а DWORD - 4.
Знаю, что иногда, в виду выравниваний - BYTE несмотря на sizeof() превращается в 4 - есть такой замечательный прикол.
Но есть еще одна такая замечательная вещь как:
#pragma pack (size) (принудительное выравнивание)
Что есть "динамическая память"? DRAM?
Какая бывает еще?
Почему постоянно пытаются давить авторитетом: "работаю уже далеко не первый год", "c ЯУЗа начинал" и т.п.
А должно было, судя по технике. Просто, видимо, мало работал с C++.
Ежели интересно - последние 5 лет успешно пишу и на С++ и на Паскале и на Асме знаю еще Бейсик Фортран и еще несколько на данный момент мертвых языков.
Самостоятельное проектирование и разработка нескольких крупных коммерческих проектов, причем на данный момент продаваемых хотя-бы в медицине.
Причем последний мне пришлось переписывать с нуля для одной организации - потому что предыдущий их разработчик, судя по всему такой-же большой любитель кем-то придуманных шаблонов как и ты, такого наворотил, что сам черт ногу сломит. Софт падал с завидной регулярностью.
Моя "неправильно", "некорректно" написанная прога уже наработала 8760 часов без единого отказа в жестких условиях эксплуатации. Это так - алаверды - ежели ты вообще в курсе что такое наработка на отказ.
Какое примитивный взгляд...
А для чего акробатам страховка? У них то вроде ноги к тому месту приделаны?
Ага. А значит по твоему получается так: ежели в поезде есть стоп-кран - то его обязательно нужно дернуть. Супер.
Если пишешь для себя, на коленках...
А если серьезный коммандный проект, то это не просто плохой тон, а скрытая диверсия.
Та ну! А ты вообще в скольких командных проектах участвовал чтобы так смело об этом рассуждать?
Не во всех.
Представляешь, я вот GOTO использовал всего один единственный раз в жизни - и то, во второй день, когда сел за программирование. А потом, жалость-то какая, я почему-то совершенно успешно обходился только брэйками ифами свитчами и ретурнами.
При хорошей архитектуре кода - уверяю тебя - без GOTO более чем прекрасно можно обойтись.
Ага... и без void* можно и нужно обходиться
Ага. Без всего можно обойтись! Так давайте-же забудем про защищенный режим и линейную адресацию памяти! Вернемся же к real-моду и сегментации! Будем делать все на статике! А нафига нам в таком случае вообще память нужна?
Минимум геморроя? Человек учиться, вырабатывает технику. Знаешь, сколько у него потом уйдет времени для валавливания бага, приведенного мной в начале поста?
К вопросу о коде японца. Так, для информации - это был малюсенький кусочек дизассемблера написанного этим самым японцем. Тоже, очень большим любителем шаблонного мышления. Код для перегонки одного опкода в мнемонику для сравнения у него занимал 200Кб программного кода на C++.
Для сравнения - мой вариант разбора опкода и перегонки его в мнемонику (отдельный класс у меня для этого существует) занимает в общей сложности 30Кб. из которых - 15Кб занимает текст мнемоник.
Работает быстро - и самое главное без ошибок. Никаких тайпкастов - только работа с указателями -void и char.
Правильно что человек учится. Только для того чтобы из человека получился толковый программер - он в первую очередь должен быть развит разносторонне - чтобы знать, в каких местах нужно применять одни методы, а вкаких другие. А в каких не побоялся бы предложить свой собственный вариант исполнения. А если пичкать его шаблонами - говоря что делать нужно только так, то и выйдет из него обычный шаблонный кодер, а не криэйтор.
Кодеров сейчас хватает, а вот криэйторов - маловато будет.
Прошу прощения у человека создавшего сабж и администратора форума за устроенные мною здесь препирательства со слишком самомнительным и невежливым человеком.
Смеялся долго. Оставлю сей опус без комментариев...
А ты прокомментируй, вместе посмеемся.
Если тебя так волнует данный аспект - могу посоветовать следующее - когда пишешь код, внимательнее смотри за тем ЧЕГО и КУДА передаешь. Так глядишь и проги корректнее работать будут.
Я то смотрю, поэтому и даю совет постарать обходиться без void*. А ты постоянно заглядываешь в чужой код? Какого размера проекты ты вел, что успеваешь за всем следить?
А чего в результате получаем? Ты еще скажи скрипты на вижуал бейсике.
Иногда стоит отвлечься от того "что получится", а постараться следовать спецификации языка.
Сабжект посмотри - человек вообще спрашивал о том как передавать в функцию двумерный массив.
Ну и... Создать конкретный тип двумерного массива.
Я например не вижу никакой аналогии между массивом и классом.
А аналогию между массивом и вектором?
Может ты еще скажешь что весь STL пережиток прошлого?
А причем тут STL? Теперь я не вижу аналогии между memcpy и STL. Может ты и при программировании на С используешь STL?
А C++ чем по-твоему от C отличается?
Абстракцией данных. Улучшенной типовой безопасностью, которую ты игнорируешь. Проитай "Рекомендации дл япрограммистов на С" Страуструпа, чтоб понять, что твои ошибки являются типовыми.
А ежели я так напишу:
class reader
{
private:
char *mem;
public:
BYTE read_byte(void);
DWORD read_dword(void);
};
BYTE reader::read_byte(void)
{
return mem[offset++];
}
DWORD reader::read_dword(void)
{
offset+=4;
return *(DWORD*)(mem+offset-4);
}
Тебе не кажется что это те-же яйца только в профиль?
Нет, не кажется. Только я бы еще сделал бы всё статиком.
Ну это ты вообще отмочил!
Если мне надо прочитать 1 байт а sizeof мне вернет 4 - тебе не кажется что это будет для меня совсем неподходящим вариантом.
BYTE он потому и байт что 1, а DWORD - 4.
Ты мне докажи, что тип DWORD соответствует 4 байтам. Лично я не знаю такого встроенного типа, а сл-но он может соответствовать любому значению, которое захочет программист.
Ежели интересно - последние 5 лет успешно пишу и на С++ и на Паскале и на Асме знаю еще Бейсик Фортран и еще несколько на данный момент мертвых языков.
.....................
Это на правах рекламы? Ты отвлекаешься от темы. Для меня это не авторитетно...
Это так - алаверды - ежели ты вообще в курсе что такое наработка на отказ.
Нет... не знаю... Я тринадцатилетний хАцКеР из Уть-Урюпинска.
Ага. А значит по твоему получается так: ежели в поезде есть стоп-кран - то его обязательно нужно дернуть. Супер.
Несколько иначе. Если есть опасность для пассажиров и техники, и эту опасность можно уменьшить с помощью стоп-крана, то в поезде должен быть стоп-кран.
Та ну! А ты вообще в скольких командных проектах участвовал чтобы так смело об этом рассуждать?
Я скромный ХаЦкЕр из Усть-Урюпинска.
Ага. Без всего можно обойтись! Так давайте-же забудем про защищенный режим и линейную адресацию памяти! Вернемся же к real-моду и сегментации! Будем делать все на статике! А нафига нам в таком случае вообще память нужна?
Ну ты же обходишься без обеспечения типовой безопасности. Кстати, с этой позиции, ты остался в древних временах С.
Тоже, очень большим любителем шаблонного мышления.
Поясни, что значит шаблонное мышление и "тоже".
Для сравнения - мой вариант разбора опкода и перегонки его в мнемонику ......
Опять на правах рекламы?
А если пичкать его шаблонами - говоря что делать нужно только так, то и выйдет из него обычный шаблонный кодер, а не криэйтор.
Я конкретно указал ошибку и показал её критичность, а ты продолжаешь сопротивляться.
Прошу прощения у человека создавшего сабж и администратора форума за устроенные мною здесь препирательства со самомнительным и невежливым человеком.
Себя прорекламировали, других похаили...
P.S. Здесь есть компетентные люди, которые нас рассудят.
А так же скажите, где я был "самомнительным и невежливым человеком".
Как лучше передать функции двумерный массив?
Смотря в каких обстоятельствах. Опиши, pls, подробнее свою задачу.
А ты прокомментируй, вместе посмеемся.
А самому слабо догадаться, раз уж ты у нас такой куль программер на C++? Подумай хорошенько - книжку умную почитай - у тебя получится.
Как ты там написал? Пусть человек покопается разберется где ты допустил ошибку? Так вот теперь предлагаю тебе внимательней разобраться с тем что ты написал и найти в своем "примере" свои же глупости.
Я то смотрю, поэтому и даю совет постарать обходиться без void*. А ты постоянно заглядываешь в чужой код? Какого размера проекты ты вел, что успеваешь за всем следить?
Если хочешь знать, чужого кода я пересмотрел ой как не мало и асмового и cpp-шного. Достаточно для того чтобы в отладчике по асмовому коду восстановить сишный код - и сказать - где горе программеры регулярно делают ляпы.
Иногда стоит отвлечься от того "что получится", а постараться следовать спецификации языка.
Иногда стоит задуматься о том, что спецификация не есть свод ОБЯЗАТЕЛЬНЫХ законов и правил, чтобы как барану лбом переться в закрытые ворота.
А аналогию между массивом и вектором?
А давай к машине пятое колесо приделаем - тоже круто будет.
Абстракцией данных. Улучшенной типовой безопасностью, которую ты игнорируешь. Проитай "Рекомендации дл япрограммистов на С" Страуструпа, чтоб понять, что твои ошибки являются типовыми.
Сильно сказано. Очень сильно.
А ты вообще хоть знаешь что из себя представляет класс так сказать физически - как все это работает? Или только в книжках да хелпах начитался описаний мнемоник?
Советую покопаться отладчиком в любом коде с классами - посмотри как все это работает - глядишь и на вопросы смотреть ширше будешь.
Нет, не кажется. Только я бы еще сделал бы всё статиком.
Ишь какой умный. Ты вообще допускаешь мысль - что я привел только отрывок кода и мне этот класс как static нафиг не нужен а нужен именно как dynamic?
Ты мне докажи, что тип DWORD соответствует 4 байтам. Лично я не знаю такого встроенного типа, а сл-но он может соответствовать любому значению, которое захочет программист.
Ну это вообще...
Объясняю доходчиво для тех кто в танке.
DWORD - от Double Word.
А теперь к азам программирования.
Минимальная единица информации - 1 бит.
Минимальная операционная единица - 1 байт = 8 бит.
1 машинное слово состоит из 2 байт тобишь 16 бит.
2 машинных слова соответсвенно 32 бита. тоесть 4 байта.
Делить умножать умеем?
Я разговариваю за конкретные величины а не за абстрактные названия.
И ежели ты не в состоянии провести конкретное указание той или иной величины - извини, но это твои проблемы.
Это на правах рекламы? Ты отвлекаешься от темы. Для меня это не авторитетно...
Ты спросил - я ответил. Мне стесняться нечего.
И я не авторитет себе зарабатываю - просто ты видать считаешь себя слишком умным чтобы говорить мне, что я мало на C++ работал.
Нет... не знаю... Я тринадцатилетний хАцКеР из Уть-Урюпинска.
По тебе и видно. Возрасту мало. Опыта тоже. Гонору - выше крыши.
Я скромный ХаЦкЕр из Усть-Урюпинска.
См. выше. Поучаствуй в командных проектах с разными командами - глядишь мнение-то и изменится.
Ну ты же обходишься без обеспечения типовой безопасности. Кстати, с этой позиции, ты остался в древних временах С.
Да, наверное поэтому я по-прежнему веду успешные коммерческие разработки как ведущий программист - и наверное поэтому софт который мы разрабатываем отличают высокие показатели по скорости и надежности.
Но нашему юному гению C++ конечно-же со своей колокольни виднее кто где остался.
Поясни, что значит шаблонное мышление и "тоже".
Что такое шаблон знаешь? Видать нет.
Поясню - шаблонное - это когда напрочь отсутствует творческий процесс, а есть лишь заученная последовательность выполняемых действий. Плюс ко всему - мнение что существует два мнения - одно твое - другое неправильное.
А "тоже" - потому что все больше убеждаюсь что ты мыслишь именно шаблонами.
Опять на правах рекламы?
А пусть даже и реклама. Мне за свои проги никогда краснеть не приходилось.
Я конкретно указал ошибку и показал её критичность, а ты продолжаешь сопротивляться.
Кто тебе сказал что я сопротивляюсь?
Я не сопротивляюсь. Просто я не люблю когда мне с эдакой учительской заботой начинают втирать чего и как мне следует делать. Особенно те - кому это делать не по силам - ни по рангу ни по знаниям.
Сначала научись тому что твое мнение не идинственное правильное - всегда найдется намного правильнее. А потом уже лезь со своими поучениями - хотя как раз именно это и является ПЛОХИМ ТОНОМ.
Себя прорекламировали, других похаили...
P.S. Здесь есть компетентные люди, которые нас рассудят.
А так же скажите, где я был "самомнительным и невежливым человеком".
См. Выше. В предыдущем абзаце ответы на все твои вопросы.
Советы и поучения - две совершенно разные вещи. И этим разговором я тебе просто указал на твою ошибку - нет не в программе - а в культуре общения - тобишь невежливость.
А вот ты по-прежнему продолжаешь сопротивляться - в чем как раз и выражается твоя излишняя самомнительность - как же - все кругом .... один ты у нас дартаньян.
Я все понятно объяснил - или мне еще раз придется повторять для тех кто в танке?
To Green:
А самому слабо догадаться, раз уж ты у нас такой куль программер на C++? Подумай хорошенько - книжку умную почитай - у тебя получится.
Как ты там написал? Пусть человек покопается разберется где ты допустил ошибку? Так вот теперь предлагаю тебе внимательней разобраться с тем что ты написал и найти в своем "примере" свои же глупости.
Это не моя ошибка. Это типовая ошибка возникающая при использовании void*. Хотя, в свое время я допускал подобные ошибки и теперь стараюсь объяснить их значимость другим.
Прошу прощения перед "гостями и жителями" данного форума за дальнейший оффтоп и обсуждение моей личности.
To Green:
А ты вообще хоть знаешь что из себя представляет класс так сказать физически - как все это работает?
Знаю.
To Green:
Ишь какой умный. Ты вообще допускаешь мысль - что я привел только отрывок кода и мне этот класс как static нафиг не нужен а нужен именно как dynamic?
Ты злишься?
To Green:
Ну это вообще...
Объясняю доходчиво для тех кто в танке.
DWORD - от Double Word.
Ты меня разочаровываешь. Ты знаешь, что такое встроенные типы?
To Green:
Я разговариваю за конкретные величины а не за абстрактные названия.
И ежели ты не в состоянии провести конкретное указание той или иной величины - извини, но это твои проблемы.
Сила С++ как раз в абстрактности, я это уже упоминал.
To Green:
Ты спросил - я ответил.
Я не спрашивал
To Green:
По тебе и видно. Возрасту мало. Опыта тоже. Гонору - выше крыши.
........................
Ты уверен, что я моложе тебя?
Ты знаешь про мой опыт?
To Green:
я тебе просто указал на твою ошибку - нет не в программе - а в культуре общения - тобишь невежливость.
Конкретные места, пожалуйста, для "тех, кто в танке"
Кстати, ты не ответил на вопрос про STL.
To Green:
А самому слабо догадаться, раз уж ты у нас такой куль программер на C++? Подумай хорошенько - книжку умную почитай - у тебя получится.
Как ты там написал? Пусть человек покопается разберется где ты допустил ошибку? Так вот теперь предлагаю тебе внимательней разобраться с тем что ты написал и найти в своем "примере" свои же глупости.
Это ведь ты считаешь, что приведенный опус смешон.
Так почему бы тебе не прокомментировать?
Давай посмеемся над слегка видоизмененным опусом:
struct A
{
virtual ~A() {}
};
struct B
{};
class C : public A, public B
{};
void func1(void* p)
{
B* pB = (B*)p;
std::cout << p << '\n';
}
void func2(B *pB)
{
std::cout << pB << '\n';
}
int main()
{
C c;
func1(&c);
func2(&c);
return 0;
}
Да, но когда люди перестают придерживаться общих правил, получается вавилонская башня. В больших проектах итак заметная доля времени уходит на коммуникации. А ты еще предлагаешь не придерживаться общего языка...
Будет нелепо. Так же, как и неоправданное приведение указателей из одного типа в другой и обратно...
А ты вообще хоть знаешь что из себя представляет класс так сказать физически - как все это работает? Или только в книжках да хелпах начитался описаний мнемоник?
Советую покопаться отладчиком в любом коде с классами - посмотри как все это работает - глядишь и на вопросы смотреть ширше будешь.
Приведи пример чего-нибудь полезного, что ты откопал, сидя в отладчике над кодом с классами?
Минимальная операционная единица - 1 байт = 8 бит.
1 машинное слово состоит из 2 байт тобишь 16 бит.
2 машинных слова соответсвенно 32 бита. тоесть 4 байта.
Если приводишь подобные цифры, то уточняй, какую платформу ты имеешь в виду. А то можно и впросак попасть. Кроме того, встроенного типа DWORD в C++ нет. Следовательно, никто не мешает мне обозвать, например, строку, содержащую словосочетание из двух слов, DWORD'ом. О чем, собственно, и говорилось...
Я разговариваю за конкретные величины а не за абстрактные названия.
Есть конкретная величина - 1 доллар. Но есть его разновидности: доллар США, австралийский, канадский, гонконгский, брунейский, ...
Ты тоже не привел конкретного указания величины...
И я не авторитет себе зарабатываю - просто ты видать считаешь себя слишком умным чтобы говорить мне, что я мало на C++ работал.
Два психоаналитика разговаривают:
Первый: Я себе такую машину купил... (далее следует описание крутизны машины)...
Второй: Мы же с Вами профессионалы! Давайте просто достанем и померяемся...
Что такое шаблон знаешь? Видать нет.
Поясню - шаблонное - это когда напрочь отсутствует творческий процесс, а есть лишь заученная последовательность выполняемых действий. Плюс ко всему - мнение что существует два мнения - одно твое - другое неправильное.
А "тоже" - потому что все больше убеждаюсь что ты мыслишь именно шаблонами.
Из твоего сообщения не было ясно, о каком шаблонном мышлении идет речь. Есть шаблоны в традиционном понимании, а есть шаблоны С++. Последовал вопрос, что ты имеешь в виду? Судя по твоему ответу, о шаблонах у тебя одностороннее представление...
По поводу вашего примера.
Может я чего не понимаю, но что по вашему мнению в нем
некорректно работает?
Чуть-чуть расширил задачу - откомпилил, проверил - все
работает на удивление хорошо:
struct A
{
virtual ~A() {}
char other[40];
};
struct B
{
char something[40];
};
class C : public A, public B
{
public:
char text[20];
};
void func1(void* p)
{
C* pB = (C*)p;
std::cout << pB->text << '\n';
std::cout << pB->other << '\n';
std::cout << pB->something << '\n';
}
void func2(B *pB)
{
std::cout << pB->something << '\n';
}
void main(void)
{
C c;
strcpy(c.text,"Test string");
strcpy(c.other,"Other Test string");
strcpy(c.something,"And what?");
func1(&c);
func2(&c);
return 0;
}
Извините, но придумывать что-то более изящное просто лениво,
у меня других дел хватает.
Чтобы понять яснее что именно Вас так смущает в этом коде -
напишите подробно - я отвечу по каждому из пунктов.
Еще такое дополнение:
Успех, надежность и прочие важные параметры любого программного
продукта в первую очередь зависят от того, насколько грамотно он
спроектирован.
Извините конечно, но приведенная вами помойка не может быть
результатом серьезного и вдумчивого проектирования.
Помните такую цитату - все гениальное просто? Будьте проще в
своих изысканиях и люди к вам потянутся.
Не делай кросс-оверов и не будешь от них страдать.
Далее.
Если я пишу какой-то конкретный метод класса или процедуру - я
всегда знаю, какой диапазон параметров будет в нее
передаваться. А зная это - ЛЮБОЙ мало-мальски грамотный программер
сможет реализовать ее так, что все будет отрабатывать на сто
процентов корректно. Ну а уж если у него руки не к тому месту
приделаны - то это его сугубо личные проблемы. Программированием
ему тогда заниматься не стоит.
Снова вернемся к долго муссировавшейся теме передачи параметров
через void и прочие типы указателей. Признаюсь -
я войд практически никогда не использую - всегда работаю через
char указатель.
Заранее предупрежу: разговор у нас идет о Виндах. Я не рассматриваю
ни линуха ни все прочее - это отдельная тема для разговора.
Пример:
void voidptr(void *vptr);
void charptr(char *cptr);
void dwordptr(DWORD *dptr);
void func2(B *pB);
Вот почему я так часто говорю об ассемблере.
Как это в конечном итоге выглядит в виде машинных кодов:
не скажу что точно так (зависит от компилятора, метода вызова и пр.),
но суть такая.
для простоты и наглядности использую stdcall
mov eax, vptr
push eax
call voidptr
mov eax, cptr
push eax
call charptr
mov eax, dptr
push eax
call dwordptr
mov eax, pB
push eax
call func2
Надеюсь, никто не будет возражать против того что в данном случае
32 битный регистр eax будет содержать линейный адрес
(4 байтовое число ничего более) памяти для vptr, cptr, dptr и pB
(указатель на класс - прошу заметить) соответсвенно?
<>
Это не моя ошибка. Это типовая ошибка возникающая при использовании
void*. Хотя, в свое время я допускал подобные ошибки и теперь стараюсь
объяснить их значимость другим.
<>
Смотрите пример выше. Где Вы здесь видите ошибку?
Наверное тяжело отыскать черную кошку в темной комнате,
особенно если ее там нет.
Так в чем тогда, по Вашему мнению, может возникнуть "НЕКОРРЕКТНОСТЬ"
передачи параметров например через void указатель, а?
Объясните, будьте так добры.
Можете тогда заодно объяснить что если через void передавать не
желательно - то почему тогда этот тип до сих пор еще не прибили?
Наверное для этого были достаточно веские причины.
<>
Знаю.
<>
Видимо слабо, раз такую ерунду городить изволите.
<>
Ты злишься?
<>
Ни капельки. Мне-то чего на Вас злиться?
<>
Ты меня разочаровываешь. Ты знаешь, что такое встроенные типы?
<>
Очаровывать никого не пытался - не мой профиль.
Говорите DWORD нету такого стандартного типа?
Опять вернемся к ассемблеру.
db
dw
dd
dq
надеюсь никому не надо объяснять что это значит?
Тогда, надеюсь, вопрос о том что такое DWORD и сколько байт он
занимает - снимается.
Если все-таки не понятно - обратитесь за помощью к справочникам
по ассемблеру и спецификации Intel.
<>
Сила С++ как раз в абстрактности, я это уже упоминал.
<>
Абстрактность силой являться не может.
Абстрактность - не понимание проблемы до конца.
Понимание проблемы - четкость и ясность понимания и
изложения способа ее решения.
<>
Я не спрашивал.
<>
Прочитай сабж сначала.
<>
Ты уверен, что я моложе тебя?
Ты знаешь про мой опыт?
<>
Цитирую:
Я тринадцатилетний хАцКеР из Уть-Урюпинска.
Как сказано - так и понято.
Серьезный программер не будет "носиться" со своей идеей
"правильности" как старая дева со своей девственностью,
и, соответсвенно, навязывать другому исключительную
правильность своего мнения, ибо программирование это путь
к единой цели разными тропами: изящными, быстрыми, на скорую руку,
кривыми и т.д.
<>
Конкретные места, пожалуйста, для "тех, кто в танке"
Кстати, ты не ответил на вопрос про STL.
<>
Все описанное выше - я высказывал и ранее - безрезультатно.
Видать в танке аккустика сплоховала.
STL - приводил в виде примера. Не понимаю - чего в
данном контексте неясно?
<>
Это ведь ты считаешь, что приведенный опус смешон.
Так почему бы тебе не прокомментировать?
Давай посмеемся над слегка видоизмененным опусом:
<>
Смейся на здоровье. Все хохмы см. выше.
<>
Да, но когда люди перестают придерживаться общих правил,
получается вавилонская башня. В больших проектах итак заметная
доля времени уходит на коммуникации. А ты еще предлагаешь не
придерживаться общего языка...
<>
Чтобы не получалась вавилонская башня - за этим должны следить
проектировщики и ведущие программисты. И если они не в состоянии
этого сделать - то грош цена тому проекту и никакая стандартизация
типов Вас не спасет - сколько бы вы не утверждали обратное.
<>
Будет нелепо. Так же, как и неоправданное приведение указателей
из одного типа в другой и обратно...
<>
Еще более нелепо плодить тайпкасты, там где без них можно прекрасно
обходиться.
<>
Приведи пример чего-нибудь полезного, что ты откопал,
сидя в отладчике над кодом с классами?
<>
А самостоятельно силенок не хватит разобраться? Посмотри выше - мож
чего и найдете Сами.
<>
Если приводишь подобные цифры, то уточняй, какую платформу
ты имеешь в виду. А то можно и впросак попасть. Кроме того,
встроенного типа DWORD в C++ нет. Следовательно, никто не мешает
мне обозвать, например, строку, содержащую словосочетание из двух
слов, DWORD'ом. О чем, собственно, и говорилось...
<>
См. Выше.
Скажу более DWORD - это базовый тип - а int и все иже
с ними - не более чем знаковые расширения.
К словам придираться - удел критиков, а критики получаются из
неудавшихся программистов в том числе.
Читайте доки по asm-у чтобы понять что такое DWORD.
Такого стыдно не знать ребята.
<>
Есть конкретная величина - 1 доллар.
Но есть его разновидности: доллар США, австралийский, канадский,
гонконгский, брунейский, ...
<>
Речь идет об IA32 а не о долларах и кросс-платформах.
<>
Ты тоже не привел конкретного указания величины...
<>
Цитирую Ваши слова:
<>
Минимальная единица информации - 1 бит.
Минимальная операционная единица - 1 байт = 8 бит.
1 машинное слово состоит из 2 байт тобишь 16 бит.
2 машинных слова соответсвенно 32 бита. тоесть 4 байта.
--------------------------------------------------------------------------------
Если приводишь подобные цифры, то уточняй, какую платформу
ты имеешь в виду. А то можно и впросак попасть. Кроме того,
встроенного типа DWORD в C++ нет. Следовательно, никто не мешает
мне обозвать, например, строку, содержащую словосочетание
из двух слов, DWORD'ом. О чем, собственно, и говорилось...
<>
Чего и где я не указал? Могу написать в hex-е ежели с десятичной
арифметикой проблемы.
Минимальная единица информации - 0x1 бит.
Минимальная операционная единица - 1 байт = 0x8 бит.
1 машинное слово состоит из 2 байт тобишь 0x10 бит.
2 машинных слова соответсвенно 0x20 бита. тоесть 0x4 байта.
Азы информатики - преподают еще в школе. Долее на эту тему
распространяться не имею желания.
<>
Два психоаналитика разговаривают:
Первый: Я себе такую машину купил... (далее следует описание
крутизны машины)...
Второй: Мы же с Вами профессионалы! Давайте просто достанем и
померяемся...
<>
Прекрасный анекдот.
Намек не понял, простите.
<>
Из твоего сообщения не было ясно, о каком шаблонном мышлении
идет речь. Есть шаблоны в традиционном понимании, а есть шаблоны С++.
Последовал вопрос, что ты имеешь в виду? Судя по твоему ответу, о
шаблонах у тебя одностороннее представление...
<>
Словоблудием заниматься неинтересно.
Если из написанного не был понятен смысл фразы "шаблонное мышление"
No comments...
Развивать эту тему далее с замкнутыми на самих себя людьми
не имею больше желания. Простите.
Обсуждение переросло в бросание тортами.
Форум предназначен для тех, кто хочет получить возможно разновариантные
ответы на свои вопросы, а не для выяснения кто круче.
Каждому работодатель воздаст по заслугам :)
Сегодня попрошу администратора вырезать этот бесполезный спор из
данного сабжекта.
Еще раз прошу прощения у админа и автора темы.
Чистота - залог здоровья.
Не надо мусорить - да?
Если есть желание пообщаться по теме без топтания на месте словами и
мыслями, то предлагаю продолжить обсуждение данного вопроса в отдельной
конфе или можете писать мне на мыло: [email]begemot_cat@mail.ru[/email]
Специально для Green и Mozhay:
Может я чего не понимаю, но что по вашему мнению в нем некорректно работает?
Если ты его откомпилировал и запустил, то не мог не заметить, что адрес, выводимый ф-цией func1() не совпадает с адресом, выводимым функцией func2(). Хотя передавали мы туда указатель на один и тот же объект. Вот и тонкости приведения типов. Думаю, понятно, что виртуальный деструктор класса A там не просто так...
Чуть-чуть расширил задачу - откомпилил, проверил - все работает на удивление хорошо:
{
C* pB = (C*)p;
...skipped...
}
Ну вот и поправил так, что все самое интересное пропало. Я то предлагал приводить к типу B*. Если не прибегать к опасным приведениям типов все прекрасно работает... В качестве указателя на базовый класс передаем указатель на производный. Основы полиморфизма... Без этого С++ лишь немногоим лучше, чем просто С. Пример, конечно, натянутый, но, поскольку приведениями типов не страдаю уже довольно давно, в голову ничего более правдоподобного не пришло.
Кстати, если вспомнить про memset, то вот типичные грабли:
struct A
{
virtual ~A() {}
int x;
};
int main()
{
A *a = new A;
memset(&a, 0xff, sizeof(a));
delete a;
return 0;
}
Выше я постарался показать, что меня смущает. Ваше слово?
Успех, надежность и прочие важные параметры любого программного продукта в первую очередь зависят от того, насколько грамотно он спроектирован.
Извините конечно, но приведенная вами помойка не может быть результатом серьезного и вдумчивого проектирования.
Бесспорно. Что же касается помойки, то она и не претендует на звание серьезного продукта. В серьезном продукте подобные ошибки обычно неплохо маскируются. Здесь же выделено только самое необходимое, чтобы воспроизвести ошибку.
Если говорить про указатели на void (или на char, не играет роли), то что сделает программер в случае:
Диапазон параметров - указатель на объект класса A или производного от A класса.
Я тоже признаюсь, что довольно часто все же использую указатели на char*. Но это тогда, когда мне просто нужно указать на некий буфер в памяти.
Надеюсь, никто не будет возражать против того что в данном случае 32 битный регистр eax будет содержать линейный адрес (4 байтовое число ничего более) памяти для vptr, cptr, dptr и pB (указатель на класс - прошу заметить) соответсвенно?
Если быть точным, то не указатель на класс, а адрес объекта данного класса. Вот если бы в асме были user-defined types, то можно было бы говорить об указателе на класс (а точнее - на объект класса)
Так в чем тогда, по Вашему мнению, может возникнуть "НЕКОРРЕКТНОСТЬ" передачи параметров например через void указатель, а? Объясните, будьте так добры.
Передача параметра, как void* с последующим приведением дала совсем другой результат, нежели типизированная передача параметра... Не ошибка?
Наверное для этого были достаточно веские причины.
Например, чтобы не усложнять грамматику языка.
И еще, чтобы сохранить совместимость с C.
Говорите DWORD нету такого стандартного типа?
Опять вернемся к ассемблеру.
dw
надеюсь никому не надо объяснять что это значит?
Тогда, надеюсь, вопрос о том что такое DWORD и сколько байт он занимает - снимается.
Начали за здравие, кончили за упокой... Кто здесь говорил про асм? Речь шла о С++. А там, если я захочу, никто не помешает мне создать свой тип DWORD. И что же, мое творение будем считать стандартным типом?
Абстрактность силой являться не может.
Абстрактность - не понимание проблемы до конца.
Понимание проблемы - четкость и ясность понимания и изложения способа ее решения.
Если человеку, чтобы сделать шаг, нужно было бы целенаправленно мысленно давать команды мышцам, то он бы умер, так и не шагнув. Абстракция - возможность мыслить категориями более высокого уровня. Любой язык программирования (даже ассемблер) дает человеку абстрагироваться от машинных кодов и начать заниматься делом.
Абстракция - более, чем понимание проблемы. Это обобщение проблемы с частного случая на более общие. По твоему выходит, что все теоретики и практики ООП уже не первый десяток лет маются какой-то ерундой, пытаясь предоставить программисту как можно больше возможностей для абстракции? Зачем тогда вся эта цепочка:
процедурное программирование
объектно-ориентированное программирование
обобщенное программирование
?
STL - приводил в виде примера. Не понимаю - чего в данном контексте неясно?
Если ты про это:
Может ты еще скажешь что весь STL пережиток прошлого? Может его и юзать ненадо? А чем ты собсно данные копировать будешь? Может ReadFile-ом или еще того круче в цикле for???
А C++ чем по-твоему от C отличается?
Ну, во-первых, никто не заставляет его юзать (из второго предложения можно сделать вывод, что использовать его надо обязательно)
Во-вторых, memcpy (а также memset и memmov) не имеют никакого отношения к STL. И как тогда понимать твое недоумение? Про ReadFile, конечно, сострил... Но вот цикл for никто не отменял. Или std::copy, или еще какие алгоритмы...
//===================================
Смейся на здоровье. Все хохмы см. выше.
Какие уж там хохмы... Печально это...
Чтобы не получалась вавилонская башня - за этим должны следить проектировщики и ведущие программисты. И если они не в состоянии
этого сделать - то грош цена тому проекту и никакая стандартизация типов Вас не спасет - сколько бы вы не утверждали обратное.
Не надо валить с больной головы на здоровую. Наверное, проектировщикам и ведущим программистам больше делать нечего, кроме как надзирать за младшими программистами.
Кроме того, ты, видимо, испытываешь удовольствие, когда видишь всяческие эзотерические конструкции в коде, изобретенные по сотому разу велосипеды вместо использования стандартных средств и т.д. Я же предпочитаю общаться на хорошо устоявшемся языке.
Абсолютно верно. Неоправданные тайпкасты вредны. А оправданными онм бывают довольно редко. И я стараюсь к ним не прибегать. Это была твоя идея передавать данные, как указатель на void. Как ты ими воспользуешься без приведения?
Приведи пример чего-нибудь полезного, что ты откопал, сидя в отладчике над кодом с классами?
А самостоятельно силенок не хватит разобраться? Посмотри выше - мож чего и найдете Сами.
Ну что же, ничего полезного не вижу. Тривиальные вещи. И незачем время в отладчике ради этого терять.
Если говоришь, что это базовый тип, то уточняй, где он таковым является. В С++ нет такого типа.
А что понимается под DWORD в асме или в WinAPI я прекрасно знаю. Но ты ведь смешиваешь тут все в одну кучу...
Речь идет об IA32 а не о долларах и кросс-платформах.
Вот теперь твое утверждение становится корректным.
А какой смысл ты вкладываешь здесь в слово "кросс"?
Стандартной формой представления информации в ЭВМ является машинное слово, состоящее из определенного для данного типа ЭВМ числа двоичных разрядов - битов.
Разрядность машинного слова определяется архитектурой и не всегда равна 16 битам.
Примеры: БЭСМ-6 (48 бит), Эльбрус (64 бит), PDP-8 (12 bit)
А блистать знанием шестнадцатиричной системы счисления совершенно незачем (см. анекдот).
Намек не понял, простите.
Это к тому, что все споры о том, кто круче, у кого больше опыт и т.д. - пустая трата времени.
Даже если понимать шаблонное мышление в житейском смысле, в программировании есть термин "шаблоны проектирования" (design patterns). И если человек владеет ими, то это многого стоит. И способность грамотно применять эти шаблоны говорит о человеке лишь с хорошей стороны. Это все можно добавить к разговору об абстракции и т.д.
Форум предназначен для тех, кто хочет получить возможно разновариантные ответы на свои вопросы, а не для выяснения кто круче.
Спор - не бросание тортами. Если чем-то задел, прошу прощения. Давайте жить дружно и общаться конструктивно :)
1) Приведенный анекдот очень в тему;
2) Жил-был отличный программист. Начинал он еще с машинных кодов. Шло время...Он изучил asm, fortran, ... , C. Он отлично их изучил и знает все тонкости вплоть до того во что компилируется каждый операто языка. И это достойно уважения. Он писал отличные по быстродействию и наработке на отказ проекты и это также достойно уважения. Но время шло дальше...И когда вышел С++ "со всеми удобствами", то мышление было уже не переделать. Хотелось пользоваться всей мощью своих знаний и дальше. И все бы ничего, когда этот программист сам ведет свой проект от начала до конца и все так безошибочно туда закладывает, что потом с течением времени не появляется необходимость его модификации. Но вот представим, что он ушел и другие люди должны разбираться в том, что же хотел изобразить творец сего проекта. И вот он вынужден сидеть и в отладчике и, возможно, в дизасме. А зачем? Ведь все могло бы быть сделано с использованием классов...
P.S. Все хорошо для своих задач. В космических исследованиях и т.п. до сих пор работают проги, написанные на фортране и, конечно, никто не хочет переписывать миллионы отлаженных и оптимизированных строк кода в виде классов к тому же с потерей жизненно важного быстродействия...
Но вот зачем, скажем, достигать предельной скорости открытия формочки с табличкой из БД, если пользователь не заметит разницы? Ну, можно переписать на asm'e несколько ключевых алгоритмов...А если отказаться от преимуществ С++ и абстракций, имхо должно нелинейно возрасти общее время разработки проекта. А ведь это тоже важно. Можно разработать отличный проект, но к моменту сдачи его в эксплуатацию он уже устареет...:-(
Извините, если кого обидел...
Гм...Совершенно очевидно следующее:
P.S. Все хорошо для своих задач. В космических исследованиях и т.п. до сих пор работают проги, написанные на фортране и, конечно, никто не хочет переписывать миллионы отлаженных и оптимизированных строк кода в виде классов к тому же с потерей жизненно важного быстродействия...
Но вот зачем, скажем, достигать предельной скорости открытия формочки с табличкой из БД, если пользователь не заметит разницы? Ну, можно переписать на asm'e несколько ключевых алгоритмов...А если отказаться от преимуществ С++ и абстракций, имхо должно нелинейно возрасти общее время разработки проекта. А ведь это тоже важно. Можно разработать отличный проект, но к моменту сдачи его в эксплуатацию он уже устареет...:-(
Извините, если кого обидел...
Сказано достаточно верно.
За одним маленьким исключением.
Если все это писалось в отношении меня - то скажу так:
Я писал и пишу стараясь макимально использовать все имеющиеся возможности.
Просто я считаю, что и в данное время не является неправильным использование некоторых старых и добрых методов. Я не считаю это признаком "плохого тона" и уж тем более "пережитком прошлого".
А во всем остальном верно.
Но вот зачем, скажем, достигать предельной скорости открытия формочки с табличкой из БД, если пользователь не заметит разницы? Ну, можно переписать на asm'e несколько ключевых алгоритмов...А если отказаться от преимуществ С++ и абстракций, имхо должно нелинейно возрасти общее время разработки проекта. А ведь это тоже важно. Можно разработать отличный проект, но к моменту сдачи его в эксплуатацию он уже устареет...:-(
Есть некоторые вещи, которые зачастую бывают весьма критичными по скорости - приведу небольшой пример - нужно реализовать таймер (я говорю про 3 кольцо, не про Ring0) который бы срабатывал с частотой до 1 мкс. Причем одновременно с этим должна происходить масса других действий - таких как вывод графики, и т.п.
Так вот. Такой таймер сделать можно - но есть одно маленькое но - в виду слишком малых тактовых интервалов - из-за низкой скорости к примеру GUI программы у тебя время срабатывания начнет плавать - иногда очень сильно. Отсюда два выхода - либо переходить на Ring0 либо ускорять весь остальной движок. Заказчик подумал и решил что надо ускорять движок. Вот и ускорили. И решили проблему.
А в обычных ситуациях - конечно - таких критических показателей тебе достигать не надо.
:)
Если ты его откомпилировал и запустил, то не мог не заметить, что адрес, выводимый ф-цией func1() не совпадает с адресом, выводимым функцией func2(). Хотя передавали мы туда указатель на один и тот же объект. Вот и тонкости приведения типов. Думаю, понятно, что виртуальный деструктор класса A там не просто так...
Уфф. Как же я устал объяснять.
Уж не знаю, на каком компиляторе ты это все собирал (я собирал и на VC и на Builder) - могу тебе сказать одно - когда я все откомпилировал - обращаю Ваше внимание отдельно - адреса, и в первой и во второй функции были равны.
Идем далее. Я решил разобраться - что-же Вас могло во всем этом так смущать - и решил добавить функциональные части в этот код. Добавил. Все по-прежнему продолжало работать.
Ну вот и поправил так, что все самое интересное пропало.
Стало наоборот еще интереснее.
Я то предлагал приводить к типу B*.
Да хоть к типу Ё приводи - и все равно будет работать.
Только объяви его сначала - и корректно передай.
В который раз уже начинаю разговор за корректную передачу параметров. ИЗВИНИТЕ, но уж если Вы настолько недальновидны, чтобы передав в функцию указатель на класс A (именно A). Преобразовываете его потом к B или C, или вообще другому классу - то конечно же у Вас случится Fault.
func1(void *ptr)
{
C *c=(C*)ptr;
c->something(); //fault optional
}
A *a=new A();
func1(a);
Еще раз извините господа, но вы приводите такие странные примеры, которых либо в жизни вообще не бывает либо встречается достаточно редко - и то, напомню еще раз, из-за недостаточно серьезного проектирования.
Если не прибегать к опасным приведениям типов все прекрасно работает... В качестве указателя на базовый класс передаем указатель на производный. Основы полиморфизма... Без этого С++ лишь немногоим лучше, чем просто С. Пример, конечно, натянутый, но, поскольку приведениями типов не страдаю уже довольно давно, в голову ничего более правдоподобного не пришло.
Если, как ты говоришь, адреса в func1 и func2 разные - батенька - а вы не задумывались над тем, как ОНО вообще тогда смогло заработать? Не кажется ли Вам что в Ваших рассуждениях имеет место быть большая небивочка?
Выше я постарался показать, что меня смущает. Ваше слово?
Вот мое слово. См. выше.
int main()
{
A *a = new A;
memset(&a, 0xff, sizeof(a));
delete a;
return 0;
}
Может хватит писать сюда примеры элементарного незнания основ программирования? Вы, почему-то регулярно уклоняетесь от темы, пускаясь в дебри АБСТРАКТНЫХ рассуждений. Конкретизировать надо.
Уверяю - приведенный пример ни малейшим образом не бьется с темой нашей с Вами беседы. И жаль что Вы так до сих пор и не можете этого понять.
Передача параметра, как void* с последующим приведением дала совсем другой результат, нежели типизированная передача параметра... Не ошибка?
Нет. Не ошибка. См. выше. Уже устал объяснять про корректность, недалекость умов и кривость рук.
Начали за здравие, кончили за упокой... Кто здесь говорил про асм? Речь шла о С++. А там, если я захочу, никто не помешает мне создать свой тип DWORD. И что же, мое творение будем считать стандартным типом?
Потому что экзешник у тебя исполняется не в виде сишных скриптов а в виде набора машинных команд в первую очередь. А то если послушать Вас то выходит что MFC к примеру вообще не использует API.
Поработав с асмом - проще начинаешь смотреть на многие вещи на тех-же сях. И еще раз напомню - я имею ввиду сишный код в конечном асмовом представлении.
Абстракция - более, чем понимание проблемы. Это обобщение проблемы с частного случая на более общие. По твоему выходит, что все теоретики и практики ООП уже не первый десяток лет маются какой-то ерундой, пытаясь предоставить программисту как можно больше возможностей для абстракции? Зачем тогда вся эта цепочка:
процедурное программирование
объектно-ориентированное программирование
обобщенное программирование?
Молодой человек - позвольте обратить Ваше внимание на следующую вещь:
Знаете кто такие философы?
Так вот философы - как раз и мыслят АБСТРАКТНЫМИ категориями. И именно поэтому - большая часть их измышлений ошибочна.
Плюс ко всему - я что где-то произносил пламенные речи о том что нужно писать только на C или Asm?
Я призывал здесь кого-то не писать на C++?
Я кому-то тыкал в нос тем что он "некорректно программирует"? Заметь - я даже Вам всего этого не говорил. Так что в свете это - Ваша дописка теряет всяческий смысл.
Ну что же, ничего полезного не вижу. Тривиальные вещи. И незачем время в отладчике ради этого терять.
Оставлю без комментариев. На лицо явный факт непонимания - я бы даже сказал НЕЖЕЛАНИЯ понимать.
Вот теперь твое утверждение становится корректным.
А какой смысл ты вкладываешь здесь в слово "кросс"?
Тоже самое, которое в него заложено английским языком.
Не надо валить с больной головы на здоровую. Наверное, проектировщикам и ведущим программистам больше делать нечего, кроме как надзирать за младшими программистами.
Интересная мысль.
А что они по твоему еще должны делать? Или может ты считаешь что младшие программисты должны сами решать кому что и как писать? Судя по-твоим словам именно так и получается. Извините, но здесь уже попахивает как-раз той самой вавилонской башней и хаосом, в котором Вы пытались уличить меня. Анархия!
Я приверженец СТРОГОГО порядка в работе. И как раз моя задача заключается в том, чтобы корректно составить тех. задания для каждого младшего программиста, провести типизацию всех используемых параметров в зависимости от необходимости и регулярно следить за тем, чтобы все остальные поставленную перед ними задачу отрабатывали в срок и корректно.
Кроме того, ты, видимо, испытываешь удовольствие, когда видишь всяческие эзотерические конструкции в коде, изобретенные по сотому разу велосипеды вместо использования стандартных средств и т.д. Я же предпочитаю общаться на хорошо устоявшемся языке.
Интересно знать, почему Вы пришли к такой точке зрения? Я кажется об этом не говорил. Я указал лишь на тот факт, что использую те или иные методы и средства в зависимости от надобности и ситуации - и никогда не пихаю их куда попало только по той причине что это стало модно и об этом пишут в умных книжках.
Кстати - задумайтесь над таким вопросом:
Нельзя ведь исключать такую ситуацию, что к примеру в ближайшем будущем я выпущу свою умную книжку, в которой введу свои стандарты программирования и буду насильно их вбивать в неокрепшие умы. Что Вы тогда на это скажете, когда начальство заставит Вас работать по МОИМ законам и правилам? А? Подумайте на досуге - полезно будет.
А спорить я больше не собираюсь.
Это моя последняя дописка на эту тему. Мне работать нужно.
Ежели Вы умные люди - Вы все-таки хотя-бы проанализируете все что я хотел сказать. Ежели нет - ну значит нет.
Что Вы оба из себя представляете - я прекрасно понял - и уж извините ребята - не по уровню Вам со мной общаться. Это не наезд - это констатация факта. Хотите обижайтесь - хотите не обижайтесь - это Ваше сугубо личное дело.
Захотите поспорить - все вопросы мне на мыло.
А эту словесную перепалку надо вырезать из этого сабжа.
Уфф. Как же я устал объяснять.
Уж не знаю, на каком компиляторе ты это все собирал (я собирал и на VC и на Builder) - могу тебе сказать одно - когда я все откомпилировал - обращаю Ваше внимание отдельно - адреса, и в первой и во второй функции были равны.
Собирал MSVC++ 6.0
Если у тебя они равны, то либо ты собирал не мой код, либо компилятор работает неправильно.
Адреса не могут совпадать, так как перед подобъектом базового класса B в объекте класса С есть еще подобъект базового класса А.
При передаче указателя на объект класса C в типизированную функцию компилятор правильно выделил адрес подобъекта B из объекта C.
При приведении же к void* всяческая информация о типе теряется и восстановить ее нельзя. Переданный же адрес будет указывать на подобъект базового класса A, который непустой. И как же адрес A будет равен адрусу B ?
Кстати, я привел в примере пустой класс A. Можно подумать, что с учетом empty-base-optimization он не займет места в объекте класса C. Все было бы так, если бы не указатель на таблицу виртуальных ф-ций...
Попробуй так:
struct A
{
int x;
};
struct B
{
int x;
};
class C : public A, public B
{};
void func1(void* p)
{
B* pB = (B*)p;
std::cout << p << '\n';
}
void func2(B *pB)
{
std::cout << pB << '\n';
}
int main()
{
C c;
func1(&c);
func2(&c);
return 0;
}
Возможность передачи указателя на объект производного класса туда, где ожидается указатель на объект базового класса - это одна из важнейших возможностей, предоставляемых ООП. Есть такое понятие - полиморфизм.
Еще раз извините господа, но вы приводите такие странные примеры, которых либо в жизни вообще не бывает либо встречается достаточно редко - и то, напомню еще раз, из-за недостаточно серьезного проектирования.
Вот типичный учебный пример:
{
virtual void Draw();
};
class Triangle : public Figure
{
virtual void Draw();
};
class Circle : public Figure
{
virtual void Draw();
};
void DrawFigure(Figure *figure)
{
figure->Draw();
}
int main()
{
Triangle t;
Circle c;
DrawFigure(&t);
DrawFigure(&c);
return 0;
}
Передаем указатель на Triangle в функцию, принимающуй указатель на Figure. И все нормально.
Если, как ты говоришь, адреса в func1 и func2 разные - батенька - а вы не задумывались над тем, как ОНО вообще тогда смогло заработать? Не кажется ли Вам что в Ваших рассуждениях имеет место быть большая небивочка?
А почему бы и не заработать? Я то всего лишь вывожу эти адреса на экран. Самими объектами не пользуюсь...
Может хватит писать сюда примеры элементарного незнания основ программирования?
Я привел пример и сказал, что он некорректен.
Сформулируй, пожалуйста, какую из основ программирования я в данном случае не знаю?
Уверяю - приведенный пример ни малейшим образом не бьется с темой нашей с Вами беседы. И жаль что Вы так до сих пор и не можете этого понять.
Не нужно меня жалеть. Я прекрасно понимаю, о чем пишу.
Так рассуждать о философах... Извини, если задену, но приведу лишь одну фразу и больше сюда не пишу:
Вы стоите на самой низшей ступени развития! - перекричал Филипп Филиппович, - вы еще только формирующееся, слабое в умственном отношении существо, все ваши поступки чисто звериные, и вы, в присутствии двух людей с университетским образованием, позволяете себе с развязностью совершенно невыносимой, подавать какие-то советы космического масштаба и космической же глупости о том, как все поделить, и вы в то же время наглотались зубного порошку!..
(С) М.А. Булгаков, "Собачье сердце"
Все зависит от того, как ты будешь хранить этот массив в программе.
Хранишь в виде массива - передавай указатель на первый элемент и размерности.
Если размерности фиксированы, то можно ограничиться одним указателем.
Или так
Хранишь в виде vector<vector<int> > - передавай ссылку или указатель на этот объект:
void f(const Array2D &A);
void f(Array2D &A);
void f(Array2D *A);
P.S. Извини за всю нашу перепалку с нулевым КПД...
Berg верно подметил глубинную причину спора,- закостенелость мыщления и непонимание нового и передового.
Mozhay, ты привел достойные примеры. Я еше раз убедился в твоем професионализме. Тебя, кстати, тоже записали в "молодые люди" и попытались надеть слюнявчик.
Спасибо и ddnh_bc. Я получил некоторое удовольствие от спора, пока ты не перешел на личности. Я еще больше укрепился в своем мнении, приводя конкретные примеры и обратившись к литературе. Кстати, я несколько старше тебя, поэтому позволю себе порекомендовать тебе побольше читать. Не понимааю, как ты, писатель фантаст, так плохо отзываешься о философах?
To AlexMan
P.S. Извини за всю нашу перепалку с нулевым КПД...
Присоединяюсь к извинениям.
Модератор, не удаляй эту ветку, пусть она будет примером конфликта нового со старым (я не сказал молодого со старым). Это придает форуму жизни.
Спасибо Berg и Mozhay за ваше мнение.
Berg верно подметил глубинную причину спора,- закостенелость мыщления и непонимание нового и передового.
Mozhay, ты привел достойные примеры. Я еше раз убедился в твоем професионализме. Тебя, кстати, тоже записали в "молодые люди" и попытались надеть слюнявчик.
Каждый остается при своем мнении. Ничего достойного, в приведенных примерах не увидел, уж извините.
Касаемого всего остального - для меня основным показателем всегда был, есть и останется конечный результат. И какими к нему идти путями - меня мало интересует - хотя всегда приятно, когда этот путь короток красив и изящен.
Спасибо и ddnh_bc. Я получил некоторое удовольствие от спора, пока ты не перешел на личности. Я еще больше укрепился в своем мнении, приводя конкретные примеры и обратившись к литературе. Кстати, я несколько старше тебя, поэтому позволю себе порекомендовать тебе побольше читать. Не понимааю, как ты, писатель фантаст, так плохо отзываешься о философах?
Спорить я не люблю - поскольку в спорах истина не рождается а гибнет. Если бы мне предложили дискусиию, на вышеупомянутую тему - я бы с большим удовольствием принял в ней участие. А так...
Просто стало обидно. И если вы ребята - старше - то ваше поведение можно записать вам только в минус. И мне мое тоже.
Да я пишу. И насчет философов у меня есть свое мнение так что не считаю, что я сказал что-то новое и обидное. Факты, ребята, самая упрямая вещь в мире.
Еще раз отмечу - что каждый остался при своем мнении - в чем и заключается основной недостаток споров. Куча шума и пыли - а результат 0.
Приношу свои извинения Green-у и Mozhay-ю за проявленную грубость в обращении. Но не более того.
Приношу свои извинения Green-у и Mozhay-ю за проявленную грубость в обращении.
Взаимно.
[QUOTE]
Спорить я не люблю - поскольку в спорах истина не рождается а гибнет.
Часто истина рождается после споров, когда спорщики переводят дух и могут спокойнее, без лишних эмоций, оценить результаты...
Если бы мне предложили дискусиию, на вышеупомянутую тему - я бы с большим удовольствием принял в ней участие. А так...
Ну, думаю, на эту тему больше спорить не стоит, слишком далеко мы зашли... А на какие-либо другие темы можно будет :)
Да я пишу. И насчет философов у меня есть свое мнение так что не считаю, что я сказал что-то новое и обидное. Факты, ребята, самая упрямая вещь в мире.
Чтобы быть корректным, приведи хоть какие-нибудь факты или скажи, что это сугубо твое мнение.
Приношу свои извинения Green-у и Mozhay-ю за проявленную грубость в обращении. Но не более того.
Я, в свою очередь, также приношу извинения за несдержанность и грубость.
:)