Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.64/11: Рейтинг темы: голосов - 11, средняя оценка - 4.64
2 / 2 / 0
Регистрация: 31.07.2017
Сообщений: 54

Использование дружественных функций и конструкторов преобразования

14.12.2017, 21:10. Показов 2100. Ответов 8
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Компилятор MVS 2017 выдает две ошибки:

Ошибка C2679 бинарный "+": не найден оператор, принимающий правый операнд типа "int" (или приемлемое преобразование отсутствует)

Ошибка (активно) E0349 отсутствует оператор "+", соответствующий этим операндам


На нижеописанный код:

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
#include <iostream>
using namespace std;
 
class fraction {
    int x, y;
public:
    fraction() { x = 0; y = 1; }
    fraction(int _x, int _y) { x = _x; y = _y; }
    fraction(int _x) { x = _x; y = 1; }
    void GetFraction(int & _x, int & _y) { _x = x; _y = y; }
    friend fraction operator+(fraction & ob1, fraction & ob2);
};
 
fraction operator+(fraction & ob1, fraction & ob2)
 {
    fraction TempOb;
    TempOb.x = ob1.x*ob2.y + ob2.x*ob1.y;
    TempOb.y = ob1.x*ob2.y;
    return TempOb;
}
 
int main() {
    int x, y;
    fraction fA(1, 2), fB(1, 5), fC;
    fC = fB + fA; // компилятор трактует как fС = operator+(fA,fB);
    fC.GetFraction(x, y);
    cout << x << "/" << y << endl;
 
    fC = fA + 3; // по идее эту строку компилятор должен трактовать как fC = operator+(fA,fraction(3));
    fC.GetFraction(x, y);
    cout << x << "/" << y << endl;
 
    getchar();
}
Не могу разобраться, код компилируется только если ему явно указать fC = operator+(fA,fraction(3));, а если fC = fA + 3; или fC = 3 + fA; то уже нет, хотя конструктор преобразования типа описан.
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
14.12.2017, 21:10
Ответы с готовыми решениями:

Описание и использование дружественных функций
Помогите пожалуйста! Заданы матрица и массив. Определить среднее арифметическое между максимальным значением элементов матрицы и...

Множественное наследование, Перегрузка функций, Перегрузка операторов, Использование дружественных функций и классов, Использование шаблонов классов
Здравствуйте!!! Я бы хотел попросить помоч решить...ну или скинуть примеры таких задач, если вдруг у вас они завалялись на компе или...

Добавить в программу использование дружественных функций
Вот имеется программа надо добавить к ней использование дружественных функций friend вот не могу понять как и что добавить помогите...

8
7804 / 6568 / 2988
Регистрация: 14.04.2014
Сообщений: 28,705
15.12.2017, 16:51
Лучший ответ Сообщение было отмечено Tasen как решение

Решение

C++
1
friend fraction operator + (const fraction & ob1, const fraction & ob2)
1
2 / 2 / 0
Регистрация: 31.07.2017
Сообщений: 54
15.12.2017, 17:10  [ТС]
nmcf, спасибо! Но как? Почему именно с константными параметрами все работает?
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
15.12.2017, 17:25
Цитата Сообщение от Tasen Посмотреть сообщение
код компилируется только если ему явно указать fC = operator+(fA,fraction(3));
это - нестандартное расширение компиляторов cl (visual studio)

так то - не по стандарту.
и работать в общем случае не должно.

gcc не скомпилирует, например.

Цитата Сообщение от Tasen Посмотреть сообщение
fC = fA + 3
здесь правый операнд 3
денотирует временный объект.

а временные объекты не могут биндиться на мутабельные ссылки:
Цитата Сообщение от Tasen Посмотреть сообщение
fraction operator+(fraction & ob1, fraction & ob2)

вот упрощенный пример:

http://rextester.com/XGO28972

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
 
struct fraction {};
 
fraction foo() { return {}; }
 
void non_const(fraction&) {}
void yes_const(const fraction&) {}
 
int main() {
    
    // ok. const fraction& может биндить временный объект
    yes_const( foo() ); 
    
    // error: invalid initialization of non-const reference of type ‘fraction&’ 
    //        from an rvalue of type ‘fraction’
    non_const( foo() ); 
}
0
309 / 221 / 74
Регистрация: 23.05.2011
Сообщений: 981
15.12.2017, 17:25
del
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
15.12.2017, 17:26
Цитата Сообщение от New man Посмотреть сообщение
Вообще, передача по обычной ссылке довольно плохая практика
бред.
0
309 / 221 / 74
Регистрация: 23.05.2011
Сообщений: 981
15.12.2017, 21:02
hoggy, почему бред?

Я считаю, стоит минимизировать количество неучтённых побочных эффектов при вызове функций.
А передача по ссылке только для этого и используется, по-моему.

C++
1
2
3
4
5
6
int calc_smth(int& a, int& b)
{
   .....
   b = calc_tt(); // побочный эффект, т.к. функция изменяет внешнюю переменную
   .....
}
Это же нарушение принципа единственной ответственности, так как функция кроме возврата какого-то значения, ещё меняет свой аргумент.

Если надо менять b, имхо, лучше сделать что-то такое:
C++
1
2
3
4
5
6
7
std::pair<int, int> calc_smth(const int a, int b) // создаётся копия b
{
   .....
   b = calc_tt(); // нет побочного эффекта, т.к. функция изменяет локальную переменную
   .....
   return make_pair(v, b); // возвращаем значение
}
В результате человеку при использовании функции не надо задумываться, сохранять значение b или нет и т.п.

Ну, и вот ещё. Код должен быть максимально понятен человеку. Допустим, программист никогда не видел реализацию функции, либо не помнит точно её спецификацию. И вот при чтении кода, вызывающего первую реализацию, программист может не понять, что один из аргументов изменился. Сами сравните:
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int a = 5, b = 7;
 
// b остался тем же или нет?
int d = func_indep(b);
int c = calc_smth(a,b);
// По виду кода кажется, что менялся только c, а на самом деле менялся и b
// Не понятно, изменится ли поведение, если функции поменять местами
// не понятно, можно ли их запустить параллельно
 
//*******************************
// другой вариант:
 
int d = func_indep(b);
int c;
std::tie(c, b) = calc_smth(a,b);
// На данный код достаточно мельком взглянуть, даже не зная, что делает calc_smth,
// чтобы понять:
//  1) b у нас изменилось
//  2) нельзя менять порядок вызовов двух функций
Как видно из примера, использование передачи по изменяемой ссылке заставляет программиста ДУМАТЬ, а человеческий мозг ленивый и не думает, особенно если устал. Поэтому это приводит к более высокому шансу выстрелить себе в ногу.
0
7804 / 6568 / 2988
Регистрация: 14.04.2014
Сообщений: 28,705
16.12.2017, 07:01
Твой пример слишком упрощённый. int редко по ссылке передают. Передача копий не будет побочным эффектом?
0
309 / 221 / 74
Регистрация: 23.05.2011
Сообщений: 981
19.12.2017, 18:01
Цитата Сообщение от nmcf Посмотреть сообщение
int редко по ссылке передают
Ну, это всего лишь пример, вообще, то, что я описал, не зависит от типа.
Поэтому в функциональных языках стремятся даже коллекции передавать по значению.

Цитата Сообщение от nmcf Посмотреть сообщение
Передача копий не будет побочным эффектом?
Будет, но обычно выделение памяти на стеке и создание копии не сильно влияют на результат, разве нет?
Единственные случаи, при которых это сильно может повлиять, это очень малый размер стека и наличие специфичной логики в конструкторах копирования и деструкторах, которые влияют на дальнейшее выполнение. Первый случай требует оптимизаций, поэтому там сомнительные трюки оправданы; второй случай же следствие нарушения Single Responsibility Principle, поэтому он должен решаться иначе.

P.S. Я думаю, случай изменения определённым образом коллекции может считаться исключением из моего правила, но это именно относится к оптимизациям.

P.P.S. В своём коде я стремлюсь выбирать типы параметров в следующем порядке:
1) const T& // Минимум накладных расходов, минимум побочных эффектов
2) const T // Много накладных расходов, чуть больше побочных эффектов, но внутри функции мы защищены от них
3) T // Много накладных расходов, ещё больше ПЭ
4)T& и T* // Мало накладных расходов, ограничение на передаваемые аргументы, очень мало защиты от ошибок.

И выбираю самый первый подходящий для задачи вариант.
Отмечу, что если бы ТС руководствовался вот этим правилом, у него бы не было проблемы, описанной в посте.

Добавлено через 2 минуты
P.P.P.S. В общем, я стремлюсь к тому, чтобы как можно больше объектов были неизменяемыми. Java и F# немного поломали мозги в эту сторону.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
19.12.2017, 18:01
Помогаю со студенческими работами здесь

Использование функций конструкторов
есть ли разница как использовать функцию конструктор с оператором new или без?

Использование конструкторов. Перегрузка конструкторов. Использование свойств
Помогите реализовать свойства, позволяющие осуществить проверку на допустимые значения для данных класса. using System; using...

Обработка строк, использование процедур и функций преобразования дат и времени
Приветствую. Помогите, пожалуйста, решить данную задачу: Дан список сотрудников, содержащий фамилию, имя и год рождения. Используя...

Использование функций MatLab или Вейвлет-преобразования с подавлением шума (VisualStudio)
Не знаю в какой раздел писать, простите если что Ситуация следующая, есть код написанный в MatLab, в котором используются...

Объединение конструкторов по умолчанию и преобразования
Имеется программа, реализующая размещение двухмерного динамического массива с различными фишками, типа шаблонов и т.п. Сутьную часть кода...


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

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
SDL3 для Android: Загрузка PNG с альфа-каналом с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru