15 / 15 / 4
Регистрация: 11.11.2014
Сообщений: 122

Приведение типов в классе

26.05.2015, 22:44. Показов 2140. Ответов 35
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день всем, кто увлекается.

Столкнулся с такой проблемой. Есть класс String (костыль собственного производства). Хочу перегрузить операцию сложения с прототипом:

C++ (Qt)
1
friend String operator+(const String &, const String &)
Вот кусок кода:

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
String::String(const char * s)
{
    len = strlen(s);
    str = new char[len+1];
    strcpy(str,s);
    num_strings++;
}
 
String::String()
{
    len = 0;
    str = new char[1];
    str[0] = '\0';
    num_strings++;:
}
 
String operator+(const String & st1, const String & st2) 
{   
    return String(std::strcat(st1.str, st2.str));
}
Хочу с таким определением сделать сложение:
C++ (Qt)
1
2
3
String a("Vasya");
String b;
b = "Katya " + a;
Сейчас программа вылетает с руганью на памяти. Можно ли грамотно перегрузить операцию сложения, чтобы она умела работать с таким определением. Как вариант написать явное приведение из char в структуру класса (пока ни одной мысли на эту тему). Или придётся перегружать операцию сложения в остальных двух случаях, когда одна из переменных const char *?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
26.05.2015, 22:44
Ответы с готовыми решениями:

Приведение типов
Привет всем! Компилятор выдает варнинг если сравниваются signed и unsigned значения.Допустим, код пересмотреть нельзя и изменить типы...

Приведение типов
Есть ли какая-нибудь разница в следующих выражениях: float a = 123.4f и float a = (float)123.4

приведение типов
Объясните, пожалуйста, почему возникает такая ошибка: error C2666: 'operator *' : 4 overloads have similar conversions ? Из-за того,...

35
19505 / 10108 / 2463
Регистрация: 30.01.2014
Сообщений: 17,828
28.05.2015, 00:06
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от castaway Посмотреть сообщение
Я говорю о правильном подходе, а не о через-жопном.
Лично мне не понятны твои претензии к коду Perfilov. По-моему вполне достойный подход к решению проблемы.
Ну или в реализации стандартной библиотеки, по-твоему, подход через-жопный?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  // operator+
  /**
   *  @brief  Concatenate two strings.
   *  @param __lhs  First string.
   *  @param __rhs  Last string.
   *  @return  New string with value of @a __lhs followed by @a __rhs.
   */
  template<typename _CharT, typename _Traits, typename _Alloc>
    basic_string<_CharT, _Traits, _Alloc>
    operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
          const basic_string<_CharT, _Traits, _Alloc>& __rhs)
    {
      basic_string<_CharT, _Traits, _Alloc> __str(__lhs);
      __str.append(__rhs);
      return __str;
    }
Если ты серьезно так считаешь, то предлагаю это обосновать.
0
Эксперт С++
4986 / 3093 / 456
Регистрация: 10.11.2010
Сообщений: 11,170
Записей в блоге: 10
28.05.2015, 00:12
DrOffset, мм.. а где связь о том что я говорил с тем что ты предоставил?
Под "через-жопным" я подразумевал обязательный неконстантный lhs.
0
 Аватар для Nosey
1379 / 406 / 144
Регистрация: 22.10.2014
Сообщений: 872
28.05.2015, 00:12
Цитата Сообщение от Perfilov Посмотреть сообщение
сигнатуры не совпадают специально. иначе к константному аргументу lhs нельзя будет применить неконстантный operator +=
Только зачем превращать оператор + в +=?
Это не просто сокращение строк, это чёрная магия которую надо бояться.(я про "//ну или:" вариант)

Не по теме:

castaway, Что-то нынче не в настроении :)

0
28.05.2015, 00:14

Не по теме:

Не по теме:

Цитата Сообщение от Nosey Посмотреть сообщение
castaway, Что-то нынче не в настроении:)

Всё норм:)

0
265 / 165 / 56
Регистрация: 25.02.2015
Сообщений: 435
28.05.2015, 00:18
я вот пока сочинял тут уже понаписали. тем не менее:

а мне все больше становится понятно, что я тебя лично чем-то задел. чем - хз.
я привел два примера. первый почти по всем канонам, второй - альтернатива для любителей писать хитрый код ради экономии пары строк кода.

примеры были приведены по запросу типа, покажи на сколько это просто.
примеры приведены, они простые. несовпадение сигнатур могло быть и опечаткой, однако простота реализации
была бы понятна даже новичку. тебе понадобилось зачем-то докопаться до этого и даже после пояснений что к чему - ты продолжаешь. Что значит допустим тебе нужны? ну нужны, не используй второй вариант. В случае наследников можем получить срезку объекта, которая все испортит. Хотя выглядит надуманно. Есть еще варианты? Если есть - опять же не используй.

По поводу авторитетов: Страуструп в своей книге приводит примеры именно такой реализации. Недостаточно авторитетно? Ну извини, добавить тут больше нечего.
0
 Аватар для Nosey
1379 / 406 / 144
Регистрация: 22.10.2014
Сообщений: 872
28.05.2015, 00:24
Цитата Сообщение от DrOffset Посмотреть сообщение
Ну или в реализации стандартной библиотеки
Чёрт, там же реалокация будет бонусная Мой мир перевернулся, а я так верил в стл
0
265 / 165 / 56
Регистрация: 25.02.2015
Сообщений: 435
28.05.2015, 00:26
до кучи еще раз процитирую сам себя:
Про эффективность речи пока не было. Если вдруг зайдет, то и тот и другой оператор наверно
лучше будет делать через какие-нибудь общие спец методы или функции.
и смотрим на код от DrOffset: append - тот самый спец метод. наверняка operator += тоже его юзает
или что-то подобное. лень смотреть в исходники
0
19505 / 10108 / 2463
Регистрация: 30.01.2014
Сообщений: 17,828
28.05.2015, 00:38
Цитата Сообщение от Nosey Посмотреть сообщение
Чёрт, там же реалокация будет бонусная
Необязательно. Память выделяется с запасом (вспомним про capacity). Если вторая строка не очень длинная, то она вполне влезет в этот запас. Ну а с очень длинными строками у нас проблемы уже другого рода. В любом случае, ждать от generic средства идеальной работы на всем возможном варианте входных данных - очень наивно

Добавлено через 8 минут
Nosey, В добавок к этому, реализацию можно улучшить, например, встречается и такой вариант (это из студии 2013):
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
template<class _Elem,
    class _Traits,
    class _Alloc> inline
    basic_string<_Elem, _Traits, _Alloc> operator+(
        const basic_string<_Elem, _Traits, _Alloc>& _Left,
        const basic_string<_Elem, _Traits, _Alloc>& _Right)
    {   // return string + string
    basic_string<_Elem, _Traits, _Alloc> _Ans;
    _Ans.reserve(_Left.size() + _Right.size());
    _Ans += _Left;
    _Ans += _Right;
    return (_Ans);
    }
Хотя изначальный принцип в целом сохранен.
0
 Аватар для Nosey
1379 / 406 / 144
Регистрация: 22.10.2014
Сообщений: 872
28.05.2015, 00:40
Цитата Сообщение от DrOffset Посмотреть сообщение
Необязательно. Память выделяется с запасом (вспомним про capacity). Если вторая строка не очень длинная, то она вполне влезет в этот запас. Ну а с очень длинными строками у нас проблемы уже другого рода. В любом случае, ждать от generic средства идеальной работы на всем возможном варианте входных данных - очень наивно
Это да, ну и сейчас проверил, в gcc коэффициент костантный и равен 2 у строк. -> таки миссы на примерно равных строках будут нередкими. Уж можно было в + сложить предварительно размеры, это не такой редкий оператор, обидно мальца

Добавлено через 1 минуту
Вот второй вариант - это отлично, и ведь не сложно. Эх, ГыЦыЦы
0
 Аватар для Nosey
1379 / 406 / 144
Регистрация: 22.10.2014
Сообщений: 872
28.05.2015, 01:00
Цитата Сообщение от castaway Посмотреть сообщение
В его реализации первый операнд - временная переменная
Perfilov, Сорри, я не доглядел, подумал что там ссылка чёрная магия превращается в серенькую
0
265 / 165 / 56
Регистрация: 25.02.2015
Сообщений: 435
28.05.2015, 01:08
я уже объяснил зачем так сделано. но что-то не все прониклись. в связи с этим вопросы:
что принципиально меняется? кто-то закладывался на сигнатуры с константными ссылками где-то? в стандарте что-то написано на этот счет?
интересно где? во второй реализации есть временный объект да, зато его можно менять и это избавляет
от необходимости создавать внутри функции точно такой же объект-копию. в случае с
константной ссылкой создается объект-копия внутри функции.
весь код, который компилился в случае константныйх ссылок будет компилится и когда первый - аргумент - просто объект. (ситуацию с указателями на функии не рассматриваем). срезка в случае наследования будет в обоих вариантах вроде.
1
19505 / 10108 / 2463
Регистрация: 30.01.2014
Сообщений: 17,828
28.05.2015, 01:16
Цитата Сообщение от Perfilov Посмотреть сообщение
в стандарте что-то написано на этот счет?
интересно где?
Сигнатуры операторов и методов стандартных классов есть в стандарте (см. 21.4.8.1 для string). Однако обсуждаемый класс - нестандартный. Поэтому стандарт тут упоминать можно разве только как канон, а не требование.
Я согласен с castaway, что второй вариант слегка стремный. Хотя бы потому, что убивает возможность оптимизаций, которые я выше приводил. Собственно, как я уже говорил, в эту тему я влез только для того, чтобы защитить сам подход через +=, а не какую-то конкретную реализацию.
0
265 / 165 / 56
Регистрация: 25.02.2015
Сообщений: 435
28.05.2015, 02:09
вот спец вопрос задан на эту тему:
Реализация operator + через operator +=
0
19505 / 10108 / 2463
Регистрация: 30.01.2014
Сообщений: 17,828
29.05.2015, 18:24
Цитата Сообщение от Nosey Посмотреть сообщение
Эх, ГыЦыЦы
В защиту GCC скажу, что тот код оператора рассчитан на другую оптимизацию (которая конечно не соответствует текущему стандарту (но прошлому - соответствовала), и до недавнего времени была включена всегда) - подсчет ссылок.
Т.е. конструктор копии на самом деле не выделяет память и ничего не копирует, но сохраняет ссылку на строку из параметра.
Реальное выделение памяти и копирование происходит при вызове append, где уже учитываются длины обеих строк.
1
Эксперт С++
4986 / 3093 / 456
Регистрация: 10.11.2010
Сообщений: 11,170
Записей в блоге: 10
29.05.2015, 18:37
DrOffset, Copy-On-Write?
1
19505 / 10108 / 2463
Регистрация: 30.01.2014
Сообщений: 17,828
29.05.2015, 18:39
Цитата Сообщение от castaway Посмотреть сообщение
Copy-On-Write?
Он самый.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
29.05.2015, 18:39

Приведение типов
Есть код вызова метода: obj.func(char a, char b) сам метод: void func(char a, char b) { int i = (int)a, int j = (int)b; В...

Приведение типов
Всем привет) Есть массив int a = {2 ,4 ,5 ,6 ,256} Числа располагаются по байтам в памяти так: 1б 2б 3б 4б 2 0 0 0 4 ...

Приведение типов
В паскале можно привести типы: type ts = 0..9; chislo = array of ts; Как это сделать на С++?

Приведение типов
Доброго времени суток. Пусть имеются две структуры struct Student { string FirstName; string LastName; int year;

Приведение типов
В чем различие привидения типа (type)expression, от type(expression)?


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

Или воспользуйтесь поиском по форуму:
36
Ответ Создать тему
Опции темы

Новые блоги и статьи
Часы электронные
Uhbif79 12.08.2026
Выкладываю программу часов. Программа позволяет: 1. Использовать системное время и дату, 2. Есть возможность вводить время и дату вручную. 3. Реализованы 2 будильника: начало и конец рабочего дня. . . .
Часы с будильником на основе класса QLCDNumber
Uhbif79 12.08.2026
Всем добрый день, выкладываю программу часов с будильником на основе класса QLCDNumber. Здесь я пробовал самостоятельно создавал классы, впервые столкнулся с видимостью переменной одного класса из. . .
Установка MinGW GCC 16.2 и CMake
8Observer8 10.08.2026
VK Видео: https:/ / vkvideo. ru/ video-240781534_456239017 YouTube: eY5-5PyI9NM Текстовая версия
Неделя из жизни имитационной модели склада: мои кривые руки растут, откуда надо
anaschu 10.08.2026
Неделя из жизни имитационной модели склада: как я почти написал неправильную логику и что с этим делать Работаю сейчас над учебно-рабочим проектом: строю в AnyLogic имитационную модель процессов. . .
Калькулятор для расчета родства
russiannick 07.08.2026
1. Задача: Создать калькулятор для расчета родства. Родственных связей существует 8 ступеней, такие как: p - отец P - мать q - муж Q - жена b - брат B - сестра s - сын S - дочь
Мир по моей воле
kumehtar 07.08.2026
Когда-то кажется, что всё просто. Ты весь такой светлый. Причиняешь добро. Борешься за справедливость в этом тёмном мире. Потом начинаешь замечать одну неприятную вещь. Почти каждый хороший. . .
Кредитный калькулятор
Maks 05.08.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Напишите приложение-калькулятор, которое помогает рассчитывать параметры кредита для аннуитетного и дифференцированного видов. . .
У нас сейчас поговорку "Опять 25" нужно переделать на "Опять +35".
kumehtar 04.08.2026
С ностальгией вспоминаю времена моего детства, когда у нас и правда +25 - была максимальная температура летом. Раньше +25 °C реально казались вершиной жары, когда можно было весь день пропадать на. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru