Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > C/C++: Общие вопросы > перегрузка операций |
Автор: serendip 27.1.2006, 02:22 | ||
Здравствуйте! ![]() Кто-нибудь видит что-нибудь нехорошее в этих перегрузках?
Работает(вторая) совсем непонятно, вадаёт один и тот же неожидаемый рез-т (1,35244; 1,35244; 0; 0; ...0) И при повторном запуске ошибку(куда-то чего-то не по тому адресу) |
Автор: JackYF 27.1.2006, 03:49 |
что такое DMass? полный код в студию... во второй функции не предусмотрено, мне кажется, разных размеров - откуда ты уверен, что они совпадают - опять же таки полный код DMass. что такое переменная d и чему она равна (или может быть равна?) |
Автор: threef 27.1.2006, 11:54 | ||||
Я думаю здесь: for (int i=0; i<n; i++) i<n ? либо i<v.n либо this->resize(v.getsize()); |
Автор: serendip 27.1.2006, 22:04 | ||||||
Итаак...
Перегрузка та же. Есть ещё одна перегрузка, но она выдает точно такой же результат ![]()
Размер массивов всегда совпадает(так задумывалось) Переменная d - просто обычное число, которое нужно вычесть из каждого эл-та массива. Причём, без перегрузок"^"и"~" пр-мма работает нормально - всё вводит, выводит и даже присваивает объекты (т.е. срабатывает перегр. "=", я надеюсь)
- не помогает. Такая загадка... ![]() ![]() |
Автор: BreakPointMAN 28.1.2006, 00:00 | ||||||
Итак, для начала... ![]()
а в конструкторе ты выделяешь динамически память:
Это означает, что должны быть соответствующим образом определены деструктор данного класса, а также конструктор копирования и операция присваивания. В деструкторе ты должен высвобождать выделенную конструктором память (используя delete), а копировать и присваивать объекты данного класса нужно создавая в каждом из них "свои" динамические данные.. Оператор присваивания у тебя уже определен неверно:
|
Автор: serendip 28.1.2006, 00:35 |
...ну что вам сказать...![]() ничего не понятно, кроме деструктора ![]() Могу только ответить:"А в учебнике так!":) Т.е вы хотите сказать, что в "=" нужно создавать ещё один объект? |
Автор: serendip 28.1.2006, 00:59 |
![]() ![]() Архангельский ![]() |
Автор: BreakPointMAN 28.1.2006, 01:31 |
Архангельский для изучения среды C++ Builder хорош, но никак не для изучения языка C++... ![]() ![]() |
Автор: serendip 28.1.2006, 10:15 | ||||
![]() а вот
и
- не совсем понимаю..Думается мне, что в данном случае в этом нет необходимости. Но мне очень необходмо понять, почему не работают перегрузки! ![]() При объявлении объекта я каждый раз создаю в нём свои динамические данные, разве не так? |
Автор: Fin 28.1.2006, 10:42 | ||
Скрытая логическая ошибка (в класофикации граблей № 2):
В функции создается статический объект, при выходе из функции объект автоматически уничтожается. И ссылка на него некоретна. |
Автор: Daevaorn 28.1.2006, 10:44 | ||
Приглядись, там нет ссылки. |
Автор: Fin 28.1.2006, 10:51 |
Это что return rr Да это не ссылка на объект. Но вывод за пределы функции результатов убитого уже экземпляра объекта. |
Автор: Daevaorn 28.1.2006, 11:04 | ||
Fin Тогда по твоей логике
тоже не коректно? ![]() |
Автор: Fin 28.1.2006, 11:12 | ||
Коректно. Компилятор скорее всего сделает такую последовательность команд аcсемблера.
|
Автор: Daevaorn 28.1.2006, 11:16 |
Fin Хе. А в том случае вызовет конструктор копирования. А при большом везении просто соптимизирует. |
Автор: Fin 28.1.2006, 11:16 |
Под статический объект в функции отводится память в стэке. При выходе из функции, весь стэк отведенный под функцию возврашается. И дальнейшая ссылка на данную область памяти некоректна. |
Автор: Daevaorn 28.1.2006, 11:18 |
Fin Никто не спорит. Просто ты забыл, что это С++, а не asm и компилятор занает что делает. Поверь Добавлено @ 11:20 А это совсем не верно. В стеке только локальные не статические переменные. |
Автор: Fin 28.1.2006, 11:27 | ||||
Экземпляр объекта можно создать динамически и статически. Для функции статический экземпляр объекта локален. И тут я не вижу в чем не соответствие.
Компилятору как то по барабану, что ты твориш, самое главное синтаксически правильно. Тебе искать глюки. Лучше сразу делать безглючно, чем весь день сидеть и вылавливать их. |
Автор: Daevaorn 28.1.2006, 11:40 | ||
В С++ у панятия статический своё значение, не надо путать. А глюков там нет
Это же у тебя вопросов не вызвает. |
Автор: Void 28.1.2006, 11:40 | ||||||
Такое объяснение не соответсвует принятой в C++ терминологии, и вводит в заблуждение. Локальные объекты имеют automatic storage duration, а static storage duration — это совсем другое.
Ты по-прежнему утверждаешь, что вот такой код:
Некорректен? |
Автор: Fin 28.1.2006, 11:52 |
ОК, ребята делайте как хотите. Просто меня иногда достают глюки в неожиданных местах. Поэтому я сразу подстилаю соломку. |
Автор: Void 28.1.2006, 12:03 |
Fin Забавно, а как ты тогда возвращаешь объекты из функций? Исключительно в куче? |
Автор: Fin 28.1.2006, 13:17 | ||||||||||
Ну чтож, идем к первоисточнику: т.е. к скомпилированному уже коду ![]()
Откомпилированный код, кусок, где идет вызов функции foo
Первые две строки, в стеке под адрес компилятор зарезервировал место, и передает его через стэк в функцию foo. После вызова функции вызывает деструктор, передавая this объекта через регистр cx. Сама функция foo
Парочка коментариев: Строка по адресу 00401067 идет вызов конструктора. В адрес [ebp-10h] скидывается ссылка на экземпляр класса (this) Этот адрес находится в стэке самой функции foo. Строка 0040106F идет копирование инфы с объекта созданного в функции foo в объект созданный в месте, где вызвана функция. Строка 00401080 Идет вызов деструктора экземпляра, который принадлежит функции foo. Строка 00401085 Идет возврат адреса экземпляра через регистр ax, который был передан ранее. Теперь чуть усложним программу.
Выдаваемый результат:
Прошу заметить уважаемую публику, что конструктор для экземпляра с адресом 0x0012FF7C не был вызван. Компилятор пропустил на ура, без проблем. |
Автор: BreakPointMAN 28.1.2006, 13:31 | ||
И зря тебе так думается. Даже если в конце-концов твой код заработает, неужели тебе не будет неприятно, что он написан криво?.. А если ты не сделаешь то, что тебе посоветовали, то будешь ловить, в лучшем случае, утечки памяти, либо, в худшем, Access Violation'ы. Тебе оно надо? Думаю, что нет... |
Автор: Void 28.1.2006, 13:43 | ||
12.8/15 И не ищи проблем на ровном месте. |
Автор: BreakPointMAN 28.1.2006, 13:48 | ||||
Конструктор был вызван. Но не конструктор по умолчанию (определенный тобой), а конструктор копирования (созданный неявно). Если ты задаешь его явно, то увидишь, что конструктор вызывается:
|
Автор: Fin 28.1.2006, 13:58 | ||||||||
Еше чуть усложним класс
Получаем результаты:
Теперь раскрываем ремы и делаем ch как ссылка.
Тут же получаем ошибку исполнения. предворительный результат до ошибки:
Вывод: таким способом можно пользоваться, если нет в экземпляре объекта динамических выделений памяти. |
Автор: Daevaorn 28.1.2006, 14:07 | ||
Ну ты прям Америку открыл. Понятно что в таком случае нужно самому писать конструктор копирования и оператор присваивания. Ты отвлекся от первоночалного кода, а то что ты привел ничего не доказывает, кроме как пример не до конца дописанного класса. |
Автор: BreakPointMAN 28.1.2006, 14:12 | ||
А если бы мы корректно определили конструктор копирования? ![]() Как-нибудь так (пишу сгоряча, поэтому могу насажать грубых ляпов...):
Так что совет тот же, как и serendip: читай про копирование и присваивание! ![]() Добавлено @ 14:15 Кстати, в исходной программе, открывающей данный топик одна из главных проблем как раз в отсутствии копирующего конструктора и заключается... ![]() |
Автор: LPBOY 28.1.2006, 15:49 | ||
ИМХО немного не так. Локальные объекты это те, которые объявлены в local scope. Соответственно они могут иметь как automatic storage duration, так и static storage duration. |
Автор: Void 28.1.2006, 18:12 |
LPBOY +1 Сгоряча не оговорил все возможные варианты ![]() |
Автор: serendip 28.1.2006, 20:20 |
Ужас какой...![]() ![]() И действительно, пр-мма вышла за область выделенной памяти и начала уже буквы выводить ![]() Забавно..В 1-ом сообщении от BreakPointMAN написано самое главное ![]() Ну с трудом как-то верилось.. ![]() Просто я не видела между динамически выделенной памятью и конструктором копирования никакой связи. Прошу прощенья.. ![]() |
Автор: blackofe 2.2.2006, 21:09 | ||||||||||
доусложним усложненную программу ![]()
результат:
- была вызвана функция foo, внутри которой был создан объект типа A (первая выведенная запись). - данный объект был возвращен из функции foo оператором return. при этом используется конструктор копирования, который мы сейчас доопределили явно (у тебя он не был определен, и за тебя его создал компилер) - вторая строчка вывода. обрати внимание - был создан новый объект - совершенно самостоятельный. - далее - выход из области видимости для первого объекта. для него вызывается деструктор (третья строчка вывода). - переменная s - и есть наш новый объект, который был создан путем копирования другого объекта, созданного внутри функции foo. при выходе из области видимости (функции main) для этого объекта вызывается деструктор. опять же можно обратить внимание, что деструктор вызывается для объекта, созданного конструктором копии. так что все правильно. и никакого криминала в возвращении объекта функцией нет. |
Автор: Fin 3.2.2006, 01:39 |
blackofe Я с этим разобрался. В тот же день я проделал примерно тот же самый код, что и ты привел. Что мы имеем. Двойное создание и копирование класса. При наследовании класса, все время нужно поддерживать конструктор копирования. И это все благодоря элементарной человеческой лени при написании кода. Я ленив, но не до такой степени. |
Автор: Void 3.2.2006, 07:56 | ||
Fin Знаешь, это возражения примерно из той же оперы, что и «никогда не пользуйтесь указателями, а то в вашем проекте заведутся маленькие злобные существа — меморилики». Возвращать класс по значению или на куче — исключительно вопрос семантики данного класса.
Элементарная человеческая лень привела к появлению Java и C#, где о таких вещах думать не надо. И это хорошо. |