Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > C/C++: Для новичков > Функция-член не возвращает результат (?) |
Автор: FlySabaka 8.10.2010, 11:37 | ||||||
Здравствуйте! В качестве упражнения создаю класс "больших чисел". Элементы класса: массив из 40 "цифр", знак, и длина числа. Начал реализовывать сложение двух чисел с одинаковым знаком. Реализация верная: если вставить код функции в main.cpp выдает верный ответ. Но функция addHugiInteger работает неверно. При дебаге в этой функции в списке Local variables вижу предупреждение warnind: can't find linker symbol for virtual table for HugeInteger value (см. HugeInteger.cpp строка 85). Работаю в Code::Blocks с компилятором по-умолчанию (GNU GCC compiler). Подскажите, что же я делаю не так? HugeInteger.h
HugeInteger.cpp
main.cpp
|
Автор: FlySabaka 8.10.2010, 11:58 | ||
Добавил
Пока это не принесло изменений %) |
Автор: bsa 8.10.2010, 12:30 |
На мой взгляд, в данной реализации класса конструктор копирования и оператор присваивания не нужны, так как нет выделения ресурсов подойдет и дефолтный. Вот виртуальный деструктор нужно сделать обычным, так как нефиг наследовать этот класс. FlySabaka, ты уверен, что у тебя свойство sign не может принимать нулевых значений? |
Автор: FlySabaka 8.10.2010, 12:35 |
bsa, sign может принимать нулевое значение. я предусмотрел это на случай ошибки (например инициализация объекта класса не числом типа "+234", а фигней типа "бла-бла-бла"). Пока всех проверок на корректность я в функции не сделал. Но при отладке addHugeInteger для указанных в main.cpp значений всё корректно: sign и other.getSign() равны -1. |
Автор: mes 8.10.2010, 12:50 | ||||
это весь код оператора присваивания ? Добавлено через 3 минуты и 14 секунд
в данном случае большая вероятность добавления выделения ресурсов, так что, имхо, копи конструктор добавить сразу, чтоб глаз мозолил ![]() а вот оператор присвоения для приведенного примера действительно выглядит лишним.. |
Автор: FlySabaka 8.10.2010, 12:54 |
mes, да, это весь код оператора присваивания. Code::Blocks генерит этот код при создании класса с помощью визарда (опционально). Хотя я вроде нигде не присваиваю объекты класса HugeInteger друг другу, так что этот код не используется (насколько я понимаю). |
Автор: mes 8.10.2010, 12:57 | ||
ну не знаю... ![]() |
Автор: FlySabaka 8.10.2010, 12:58 |
mes, понял. Согласен что сморозил глупость ![]() Но проблема все равно возникает до присваивания, в теле функции addHugeInteger при создании объекта res класса HugeInteger, как я и писал выше. Безусловно предпосылки к этой проблеме находятся где-то в другом месте (мож конструктор у меня какой-то не такой, а?) .. |
Автор: mes 8.10.2010, 13:03 |
ну тогда и как исправить ошибку, как мне кажется Вы уже поняли ![]() |
Автор: FlySabaka 8.10.2010, 13:05 |
mes, Вы намекаете, что ошибка в операторе присваивания? можно уточнить, в чём именно ошибка, а то недогоняю? ![]() |
Автор: mes 8.10.2010, 13:06 | ||
не стыкуется ![]() Добавлено через 2 минуты и 52 секунды раз в main выдает правильно, значит потеря идет при передаче результата поэтому вначале я предположил , что у Вас нет копи конструктора.. оказалось проще: Вы просто добавили пустой (по смыслу работы) оператор присваивания ![]() Добавлено через 5 минут и 10 секунд уберите оператор присваивания, перенеся селфхандлинг в копиконструктор (хотя можно и его убрать ) |
Автор: FlySabaka 8.10.2010, 13:16 | ||
mes, спасибо за помощь. Изменил оператор присваивания на
Приблизительно понял, почему не работает "старая версия". Буду экспериментировать ... учиться, учиться и ещё раз учиться ![]() P.S. По пути еще косяки нашёл в реализации функции, так что диву даюсь почему она мне правильно выдавала ответы непосредственно в main.cpp. |
Автор: mes 8.10.2010, 13:22 | ||
а чего self-handling закомментили ? полезная вещь ![]() а наверно из за этого : но тут я о копиконструкторе говорил ![]() в данном случае имхо нагляднее будет
|
Автор: FlySabaka 8.10.2010, 13:29 | ||
mes, здесь в операторе присваивания я его просто забыл удалить (что собственно уже сделано), в копи конструктор вставил. Я понимаю, что лимит глупых вопросов я на сегодня исчерпал, но тем не менее, как нам удаётся получить доступ к закрытым данным класса делая такой вот финт:
? Так действительно намного нагляднее ![]() |
Автор: mes 8.10.2010, 13:35 | ||
так как правила доступа распространяются на классы, а не объекты.. т.е для вашего случая : в любом объекте можно получить доступ к приватным данным другого объекта того же класса ![]() |
Автор: FlySabaka 8.10.2010, 13:39 |
mes, bsa, ещё раз спасибо за помощь![]() |
Автор: mes 8.10.2010, 14:25 |
кстати для удобства NUMBER я бы сделал не дефайном, а енумом и внутри класса.. |
Автор: Crafty 8.10.2010, 15:05 | ||
я бы вместо этой функции лучше бы перегрузил оператор + и +=, так было бы удобней и наглядней работать с классом. |
Автор: FlySabaka 8.10.2010, 17:19 | ||
Crafty, поскольку я пишу "учебный" код, то я и перегрузку операций сделаю. У меня ещё все в переди ![]()
Пока не оч понимаю, а в чём будет заключаться удобство? |
Автор: mes 8.10.2010, 17:32 | ||||
define таит в себе очень много проблем.. например игнорирование области видимости, которое заставляет выбирать для него длинные имена, чтоб избежать коллизии.. В общем придет с опытом.. а пока возьмите за правило не использовать дефайн, где можно обойтись другими средствами вот например дефайн удобно использовать как задание опции при компиляции.. т.е. что укажете компилятору, то он и подставит.. Но в таких случаях желательно использовать более уникальное имя и дать возможность его переопределить "снаружи". т.е. для Вашего случая выглядело бы примерно так :
Использование енума приносит ряд преимуществ, 1. зависимость от дефайна в одном месте, в остальном используется сам енум 2. удобство имени / отсутствие проблем с "внешними " именами 3. независимость от значения дефайна.. т.е например дефайн использует длину в байтах, а в реализации Вам удобнее мерять интегерами, тогда
4. действие дефайна становится локальным (при использовании #undef) и еще множество мелочей о которых сразу и не вспомнить ![]() |
Автор: FlySabaka 8.10.2010, 18:13 |
mes, признаться честно преимущество на данный момент мне всё равно не ясно (и где-то там, в подсознании быть может, предложенная идея кажется полезной). Про коллизии, define и длинные имена это я понял. В любом случае, совету опытных я последую. FIX: mes, вот теперь более понятны преимущества, спасибо за доходчивый ответ ![]() P.S. Первоначально я вообще хотел использовать динамические массивы, ибо меня напрягают искусственные ограничения на длину числа. Но вот посмотрел я, что на просторах интернета realloc ругают, и хают, и отказался от этой идеи (имеется в виду применение realloc в c++). Не представляю как грамотно "удлинить"/"укоротить" число (читай массив), не используя realloc (есть конечно вариант с введением временной переменной нужного размера, и копирования первого массива с последующий дозаписью новых цифр, но некрасиво ведь по-моему) |
Автор: mes 8.10.2010, 18:16 | ||
http://cplusplus.com/reference/stl/vector/ |
Автор: FlySabaka 8.10.2010, 18:20 |
mes, да-да, это я видел. может быть создам HugeInteger v.2. с использованием vector. В любом случае и такая реализация - неплохая практика для начинающего изучение C++. Тут не цель главное, а процесс ![]() |
Автор: mes 8.10.2010, 18:29 | ||||
ну вот навскидку ситуация, которая при невнимании к варнингам, может одарить долгими часами дебага
![]() |