Форум программистов, компьютерный форум CyberForum.ru

Перегрузка оператора + - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 17, средняя оценка - 4.94
GetHelp
-8 / 60 / 6
Регистрация: 27.02.2013
Сообщений: 1,112
02.08.2014, 17:56     Перегрузка оператора + #1
не получается в своем классе перегрузить оператор + пишет "error C2804: бинарный "operator +" имеет слишком много параметров", действительно задал 2 параметра, но как еще то? ведь + и подразумевает собой сложение 2х значений...
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
02.08.2014, 17:56     Перегрузка оператора +
Посмотрите здесь:

Перегрузка оператора C++
C++ Перегрузка оператора +=
Перегрузка оператора = C++
Перегрузка оператора * C++
Перегрузка оператора ~ C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
-=ЮрА=-
Заблокирован
Автор FAQ
02.08.2014, 22:14     Перегрузка оператора + #61
Цитата Сообщение от GetHelp Посмотреть сообщение
-=ЮрА=-, так уже интересно, кое что полезное взял, но не могу протестить, вы забыли дописать перегрузку оператора присваивания на ней у меня как раз сейчас все стопорится... а она точно нужна...
http://codepad.org/Vz17krvX
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
String operator = (const char * str){
        if( text )
            delete text;
        if( str )
        {
            size = strlen(str);
            text = new char[1 + size];
            size = sprintf(text, "%s", str);
            text[size] = 0;
        }
        else
        {
            text = 0;
            size = 0;
        }
        return *this;
    }
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
ValeryS
Модератор
6374 / 4840 / 441
Регистрация: 14.02.2011
Сообщений: 16,043
02.08.2014, 22:15     Перегрузка оператора + #62
Цитата Сообщение от GetHelp Посмотреть сообщение
хз я где то читал вроде что delete вызывает free сама...
это разные сущности, хотя и может delete вызывать free, а может не вызывать зависит от компилятора
Цитата Сообщение от GetHelp Посмотреть сообщение
я же показал... так и стоит и никуда не двигается
знаешь мне трудно как то по скриншотам сориентироваться
могу предложить другой путь
"отладочная печать"
после каждого выделения памяти печатаешь на экран значение указателя
например
C++
1
2
ptr = (char*)calloc(size + 1, sizeof(char))
 printf ("Copy constructor ptr=%x",ptr);
да и calloc это не new в случае неудачи исключение не бросит
так что нужно проверять
C++
1
2
3
ptr = (char*)calloc(size + 1, sizeof(char))
   if(ptr==NULL) printf("Error");
 printf ("Copy constructor ptr=%x",ptr);
GetHelp
-8 / 60 / 6
Регистрация: 27.02.2013
Сообщений: 1,112
02.08.2014, 22:19  [ТС]     Перегрузка оператора + #63
Цитата Сообщение от Tulosba Посмотреть сообщение
А вот это уже похоже на правду В плюсах постарайтесь забыть про malloc/free.
не могу забыть я лучше забуду в этом классе об new/delete просто очень уж удобная штука realloc, потому что она меняет размер, да еще и копирует элементы при этом
Tulosba
:)
Эксперт C++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
02.08.2014, 22:21     Перегрузка оператора + #64
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
C++
1
2
if( text )
* * * * * * delete text;
Говорили же уже, что не надо такую проверку делать перед delete. Лучше бы после new проверку добавил, было бы полезнее.
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
C++
1
size = sprintf(text, "%s", str);
strcpy() уже запретили? А учитывая наличие определенной ранее длины можно и вовсе memcpy обойтись.
Копировать одну строку в другую через sprintf - достойно говнокода.
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
C++
1
String operator = (const char * str){
Ссылку надо возвращать, а не копию.
-=ЮрА=-
Заблокирован
Автор FAQ
02.08.2014, 22:21     Перегрузка оператора + #65
Цитата Сообщение от GetHelp Посмотреть сообщение
просто очень уж удобная штука realloc, потому что она меняет размер, да еще и копирует элементы при этом
- нельзя её в плюсах юзать, риаллок из С-ей где совсем другой механизм обработки ошибок, тут вынужден признать, вам "слеует послушать человека который не знает что такое препроцессор" выше
GetHelp
-8 / 60 / 6
Регистрация: 27.02.2013
Сообщений: 1,112
02.08.2014, 22:22  [ТС]     Перегрузка оператора + #66
так... сейчас у меня код такой выходит
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <string>
 
class String
{
private:
    char* ptr;
    size_t size;
public:
    String() 
    {
        size = 0;
    }
    String(const char* str)
    {
        size = strlen(str);
        ptr = (char*)calloc(size + 1, sizeof(char));
        strcpy(ptr, str);
    }
    String(const String& str)
    {
        size = str.size;
        ptr = (char*)calloc(size + 1, sizeof(char));
        strcpy(ptr, str.ptr);
    }
    ~String()
    {
        if (size) free(ptr);
    }
    size_t length() const
    {
        return size;
    }
    bool SetLength(size_t NewLength)
    {
        if (!size)
        {
            size = NewLength;
            ptr = (char*)calloc(size, sizeof(char));
        }
        else
        {
            size = NewLength;
            ptr = (char*)realloc(ptr, size * sizeof(char));
        }
        return true;
    }
    const char operator[] (size_t index)
    {
        return ptr[index];
    }
    const char* operator= (const char* str)
    {
        if (size) free(ptr);
        size = strlen(str);
        ptr = (char*)calloc(size + 1, sizeof(char));
        strcpy(ptr, str);
        return str;
    }
    const String operator= (const String& str)
    {
        return operator+ (str.ptr);
    }
    const String operator+ (const char* str)
    {
        size = size + strlen(str) + 1;
        char* tmp = ptr;
        ptr = (char*)calloc(size, sizeof(char));
        strcpy(ptr, tmp);
        free(tmp);
        strcat(ptr, str);
        return *this;
    }
};
кстати ошибки пропали... но теперь не корректно просто сложение работает... например вызываю так
C++
1
2
String str("hello");
str = str + "world";
он мне в str записывает аж 20 символов, там все время повторяется helloworldhelloworld... что бы это значило?
-=ЮрА=-
Заблокирован
Автор FAQ
02.08.2014, 22:24     Перегрузка оператора + #67
GetHelp, убери realloc это действительно важно, хоть и удобно. Его нельзя даже если очень хочется
Цитата Сообщение от GetHelp Посмотреть сообщение
const String operator= (const String& str)
* * {
* * * * return operator+ (str.ptr);
* * }
- убери, юзай КК!
ValeryS
Модератор
6374 / 4840 / 441
Регистрация: 14.02.2011
Сообщений: 16,043
02.08.2014, 22:26     Перегрузка оператора + #68
Цитата Сообщение от GetHelp Посмотреть сообщение
он мне в str записывает аж 20 символов, там все время повторяется helloworldhelloworld... что бы это значило?
рекурсия однако
сам посмотри что будет, по шагам пройди
нужно предусматривать вариант, когда один аргумент является одновременно и приемником результат
GetHelp
-8 / 60 / 6
Регистрация: 27.02.2013
Сообщений: 1,112
02.08.2014, 22:26  [ТС]     Перегрузка оператора + #69
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
убери realloc это действительно важно, хоть и удобно. Его нельзя даже если очень хочется
ладно я попробую что нибудь с этим сделать...
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
- убери, юзай КК!
что юзать?
-=ЮрА=-
Заблокирован
Автор FAQ
02.08.2014, 22:27     Перегрузка оператора + #70
Цитата Сообщение от GetHelp Посмотреть сообщение
что юзать?
- конструктор копирования, который был изначально
GetHelp
-8 / 60 / 6
Регистрация: 27.02.2013
Сообщений: 1,112
02.08.2014, 22:39  [ТС]     Перегрузка оператора + #71
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
- конструктор копирования, который был изначально
C++
1
2
3
4
5
6
String(const String& str)
    {
        size = str.size;
        ptr = (char*)calloc(size + 1, sizeof(char));
        strcpy(ptr, str.ptr);
    }
этот? как и где его юзать? вы вообще о чем?

вообще я кажется понял что мне нужно, но не знаю как реализовать... мне надо все также перегрузить оператор сложения, НО не менять при этом this и при этом ухитриться вернуть из функции экземпляр String (это самое сложное, поскольку он по прежнему не валиден ) таким образом будет именно сложение, как я понял именно поэтому у меня не хочет нормально складывать...
0x10
2425 / 1597 / 232
Регистрация: 24.11.2012
Сообщений: 3,919
02.08.2014, 22:40     Перегрузка оператора + #72
Цитата Сообщение от GetHelp Посмотреть сообщение
этот? как и где его юзать? вы вообще о чем?
Речь об идиоме copy-and-swap (гуглится и, опять же, в книгах описана).
DrOffset
6424 / 3798 / 879
Регистрация: 30.01.2014
Сообщений: 6,591
02.08.2014, 22:41     Перегрузка оператора + #73
GetHelp, миллион советов уже тебе дали по конкретике, не буду повторяться.
Скажу одно, основная и главная проблема твоя в подходе к написанию кода. То, что ошибки ты сейчас самостоятельно или с помощью форумчан, исправишь - это понятно и хорошо. Но вот самый главный шаг нужно с делать в сторону того, чтобы ошибок было изначально меньше.
Начни с разделения ответственности. У тебя есть задача, задача делится на составные части. Каждую составную часть нужно описать отдельно и отдельно оттестировать, а потом собирать все воедино как конструктор. Т.е., вот скажем функция выделения памяти, она у тебя, что называется, прошита во все методы, где используется. каждый раз нужно высчитывать размер умножая на sizeof(char), каждый раз заботиться о проверке, каждый раз смотреть, чтобы указатель не попортился и т.д. Где-то можно что-то и забыть или не так посчитать. В нормальных контейнерах функцию выделения памяти обычно абстрагируют во внутреннюю функцию allocate, а освобождение, соответственно, в deallocate. Инициализация - это тоже отдельная операция. Копирование - тоже. И т.д. Принцип divide et impera очень древний и очень действенный. Не стоит пренебрегать им.
-=ЮрА=-
Заблокирован
Автор FAQ
02.08.2014, 22:45     Перегрузка оператора + #74
Цитата Сообщение от GetHelp Посмотреть сообщение
этот? как и где его юзать? вы вообще о чем?
когда запишешь
String str = String("text") + "data";
Вызовется - КП (коснтруктор преобразования) String("text")
Сработает перегруженный оператор + Strig + char
Сработает КК для str
Если бы стоял оператор присваивания String operator = String мы бы дёрнули делитом битый поинтер text
Касательно кажущегося ликиджа
str = str + "text" его не будет т.к отработает дефолтный String operator = String который по сути присвоит классу самого себя
GetHelp
-8 / 60 / 6
Регистрация: 27.02.2013
Сообщений: 1,112
02.08.2014, 22:53  [ТС]     Перегрузка оператора + #75
Цитата Сообщение от DrOffset Посмотреть сообщение
GetHelp, миллион советов уже тебе дали по конкретике, не буду повторяться.
Скажу одно, основная и главная проблема твоя в подходе к написанию кода. То, что ошибки ты сейчас самостоятельно или с помощью форумчан, исправишь - это понятно и хорошо. Но вот самый главный шаг нужно с делать в сторону того, чтобы ошибок было изначально меньше.
Начни с разделения ответственности. У тебя есть задача, задача делится на составные части. Каждую составную часть нужно описать отдельно и отдельно оттестировать, а потом собирать все воедино как конструктор. Т.е., вот скажем функция выделения памяти, она у тебя, что называется, прошита во все методы, где используется. каждый раз нужно высчитывать размер умножая на sizeof(char), каждый раз заботиться о проверке, каждый раз смотреть, чтобы указатель не попортился и т.д. Где-то можно что-то и забыть или не так посчитать. В нормальных контейнерах функцию выделения памяти обычно абстрагируют во внутреннюю функцию allocate, а освобождение, соответственно, в deallocate. Инициализация - это тоже отдельная операция. Копирование - тоже. И т.д. Принцип divide et impera очень древний и очень действенный. Не стоит пренебрегать им.
не понимаю что конкретно вы имеете ввиду под функциями выделения и освобождения памяти... что толку если я напишу скажем
C++
1
2
3
4
char* allocate(size_t size)
{
return (char*) calloc(size, sizeof(char));
}
что толку? чуть меньше писать при вызове? про остальное тоже самое...

Добавлено через 2 минуты
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
когда запишешь
String str = String("text") + "data";
Вызовется - КП (коснтруктор преобразования) String("text")
Сработает перегруженный оператор + Strig + char
Сработает КК для str
Если бы стоял оператор присваивания String operator = String мы бы дёрнули делитом битый поинтер text
Касательно кажущегося ликиджа
str = str + "text" его не будет т.к отработает дефолтный String operator = String который по сути присвоит классу самого себя
не понимаю о чем вы вы понимаете что КП не возвращает значения? конструкторы вообще не могут возвращать значение ! что именно вы пытаетесь складывать? в конечно счете вы просто присваиваете str = "data"

Добавлено через 3 минуты
т.е. КП вызванный из неоткуда ничего и не дает, вы же не вызываете его от переменной...
-=ЮрА=-
Заблокирован
Автор FAQ
02.08.2014, 23:00     Перегрузка оператора + #76
GetHelp, да ну ё моё, я же всё разложил по полкам
String str = String("text") + data
String("text") - {new String}
{new String} + data = char *operator + (char *)
String str = String(const String new Object)
что тут не ясного?
DrOffset
6424 / 3798 / 879
Регистрация: 30.01.2014
Сообщений: 6,591
02.08.2014, 23:07     Перегрузка оператора + #77
Цитата Сообщение от GetHelp Посмотреть сообщение
что толку? чуть меньше писать при вызове? про остальное тоже самое...
Толк в локализации функциональности в одном месте. Вот приведу пример из самописного класса вектор для POD.
Функция выделения памяти вынесена в отдельный внутренний метод:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    void do_realloc(size_t new_size)
    {
        if(new_size > max)
        {
            throw std::length_error("pod_vector::reserve");
        }
        T* t = (T*)::realloc(m.p, sizeof(T) * new_size);
        if(!t)
        {
            throw std::bad_alloc();
        }
        m.p = t;
        m.a = new_size;
    }
Вот методы, которые ее используют:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    void resize(size_t new_size)
    {
        if(new_size > m.a)
        {
            do_realloc(new_size);
        }
        m.n = new_size;
    }
    void reserve(size_t new_size)
    {
        if(new_size > m.a)
        {
            do_realloc(new_size);
        }
    }
А функции resize и reserve основа для всей остальной функциональности вставки и удаленния. Вот примеры:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    template<class Iter>
    void append(Iter f, Iter l)
    {
        size_t n = std::distance(f, l);
        resize(m.n + n);
        std::uninitialized_copy(f, l, m.p + m.n - n);
    }
    template<class Iter>
    void insert(iterator pos, Iter f, Iter l)
    {
        size_t i = pos - m.p;
        size_t n = std::distance(f, l);
        resize(m.n + n);
        pos = m.p + i;
        std::copy_backward(pos, m.p + m.n - n, m.p + m.n);
        std::uninitialized_copy(f, l, pos);
    }
    void push_back(T const & t)
    {
        if(m.a == m.n)
            reserve(m.n ? 2 * m.n : 2);
        m.p[m.n] = t;
        ++m.n;
    }
И теперь представь, если бы мы не выносили это в отдельные методы, а сразу писали все в реализации push_back, append и insert. Они получились бы большие и таким кодом сложно было бы управлять и отлаживать. В противоположность этому, если мы имеем набор отлаженных (пусть и самописных) компонентов, мы сможем жонглировать ими как угодно, и если вдруг какие-либо действия привели к ошибке, у нас всегда будет базовый уровень функциональности, в котором мы уверены. Это сузит круг поиска ошибки и позволит быстрее локализовать проблему. Это и есть принцип "разделяй и властвуй", который я уже упоминал.
GetHelp
-8 / 60 / 6
Регистрация: 27.02.2013
Сообщений: 1,112
02.08.2014, 23:27  [ТС]     Перегрузка оператора + #78
-=ЮрА=-, хз наверное я лучше завтра еще раз свежим взглядом на это посмотрю, но щас хоть убей не понимаю...

DrOffset, я лучше напишу общие аллокаторы...

C стиль
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
template <typename T>
T* allocate(T* ptr, size_t size)
{
    T* retval;
    (ptr) ?
        retval = (T*)realloc(ptr, size * sizeof(T)) :
        retval = (T*)calloc(size, sizeof(T));
    return retval;
}
 
template <typename T>
bool deallocate(T* ptr)
{
    bool retval = false;
    if (ptr)
    {
        free(ptr);
        retval = true;
    }
    return retval;
}
C++ стиль
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
template <typename T>
T* allocate(T* ptr, size_t size)
{
    T* retval = new T[size];
    if (ptr)
    {
        memcpy(retval, ptr, size);
        delete[] ptr;
    }
    return retval;
}
 
template <typename T>
bool deallocate(T* ptr)
{
    bool retval = false;
    if (ptr)
    {
        delete[] ptr;
        retval = true;
    }
    return retval;
}
Добавлено через 4 минуты
з.ы. сразу о возражениях касательно С стиля, да шаблоны это из плюсов, но мой компилятор это глотает... в конце концов важно лишь то в каком стиле происходит аллокация, а не то во что это обернуто...
porshe
 Аватар для porshe
52 / 46 / 17
Регистрация: 18.07.2014
Сообщений: 194
02.08.2014, 23:29     Перегрузка оператора + #79
Цитата Сообщение от 0x10 Посмотреть сообщение
std::string operator"" _s(const char* str, unsigned size) { return std::string(str, size); }
а что это за стандарт? C++11?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
02.08.2014, 23:30     Перегрузка оператора +
Еще ссылки по теме:

C++ Перегрузка оператора <<
C++ Перегрузка оператора +
C++ Перегрузка оператора <<

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
0x10
2425 / 1597 / 232
Регистрация: 24.11.2012
Сообщений: 3,919
02.08.2014, 23:30     Перегрузка оператора + #80
Цитата Сообщение от porshe Посмотреть сообщение
а что это за стандарт? C++11?
Угу. http://en.cppreference.com/w/cpp/language/user_literal
Yandex
Объявления
02.08.2014, 23:30     Перегрузка оператора +
Ответ Создать тему
Опции темы

Текущее время: 08:34. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru