Перегрузка операторов
От: Octane Россия  
Дата: 04.05.03 11:18
Оценка:
Итак... есть класс :

class Complex
{
private:
    ...
public:
    ...
    Complex operator+(Complex &other){...}
    Complex operator+(const double &other){...}
        ...
};


и есть два теста :

void main(void)
{
    Complex z(1,2);
    z=z+1;/* все работает */
    z=3+z;/* Нет такого глобального оператора или нет соответствующей заданным операторам конверсии*/
}


Вопросы:
1)как описать оператор сложения TYPE и Complex ?(TYPE — левый операнд)
2)как описать конверсию от типа TYPE к типу Complex?
Re: Перегрузка операторов
От: UltraCpp Ниоткуда ultra-cpp.narod.ru
Дата: 04.05.03 12:06
Оценка:
Здравствуйте, Octane, Вы писали:

O>
O>    z=z+1;/* все работает */
O>    z=3+z;/* Нет такого глобального оператора или нет соответствующей заданным операторам конверсии*/
O>


O>1)как описать оператор сложения TYPE и Complex ?(TYPE — левый операнд)

O>2)как описать конверсию от типа TYPE к типу Complex?
Просто, при помощи дружественных функций. Вот тебе пример.
class Complex
{
   friend Complex operator+(int fst, const Complex &Snd);
private:
    ...
public:
    ...
    Complex operator+(Complex &other){...}
    Complex operator+(const double &other){...}
        ...
};

Complex operator+(int fst, const Complex &Snd)
{
  // тут пиши что хочешь, но не забудь вернуть объект типа Complex
}


Удалено избыточное цитирование. Исправлена подсветка синтаксиса. -- ПК
Re: Перегрузка операторов
От: WFrag США  
Дата: 04.05.03 12:09
Оценка: +1
Здравствуйте, Octane, Вы писали:

O>Вопросы:

O>1)как описать оператор сложения TYPE и Complex ?(TYPE — левый операнд)

Глобальный оператор:
Complex operator+( double one, const Complex& another)
{
}


O>2)как описать конверсию от типа TYPE к типу Complex?


По-моему, конструктором:
class Complex
{
private:
    ...
public:
    Complex( double num )
    {
    }
        ...
};
7. О чем невозможно говорить, о том следует молчать.
Re[2]: Перегрузка операторов
От: template  
Дата: 04.05.03 12:44
Оценка: 5 (1)
Здравствуйте, UltraCpp, Вы писали:

UC>Просто, при помощи дружественных функций. Вот тебе пример.

UC>class Complex
UC>{
UC> friend Complex operator+(int fst, const Complex &Snd); // лишнее (template)
UC>private:
UC> ...
UC>public:
UC> ...
UC> Complex operator+(Complex &other){...}
UC> Complex operator+(const double &other){...}
UC> ...
UC>};

UC>Complex operator+(int fst, const Complex &Snd)

UC>{
UC> // тут пиши что хочешь, но не забудь вернуть объект типа Complex
UC>}

не согласен, friend тут излишество, вмешиваемся в чужой код. А так решение, лучше не придумаешь.
Re[2]: Перегрузка операторов
От: Octane Россия  
Дата: 04.05.03 16:07
Оценка:
Здравствуйте, WFrag, Вы писали:

WF>По-моему, конструктором:

class Complex
{
private:
    ...
public:
    Complex( double num )
    {
    }
        ...
};


Хм..с операторами всё отлично решилось а вот с конструкторами не очень, так можно описать только принудительную конверсию , а мне бы хотелось чтобы компилятор сам делал за меня эту грязную работу
Re[2]: Перегрузка операторов
От: UltraCpp Ниоткуда ultra-cpp.narod.ru
Дата: 04.05.03 18:55
Оценка:
Здравствуйте, WFrag, Вы писали:

WF>Здравствуйте, Octane, Вы писали:


O>Вопросы:

O>1)как описать оператор сложения TYPE и Complex ?(TYPE — левый операнд)

WF>Глобальный оператор:

WF>
WF>Complex operator+( double one, const Complex& another)
WF>{
WF>}
WF>


O>2)как описать конверсию от типа TYPE к типу Complex?


WF>По-моему, конструктором:

WF>
WF>class Complex
WF>{
WF>private:
WF>    ...
WF>public:
WF>    Complex( double num )
WF>    {
WF>    }
WF>        ...
WF>};
WF>


Прошу вас обратится к учебнику и посмотреть зачем нужен конструктор копирования.
Если:
Complex C = 10.01;
то тут нужен конструктор копирования.
А если
cout << C + 10.01 << endl;
то перегрузка оператора. И ниакак без дружественной функции необойтись (если нужен double как левый операнд).
Re[3]: Перегрузка операторов
От: WFrag США  
Дата: 05.05.03 00:08
Оценка:
Здравствуйте, UltraCpp, Вы писали:

UC>Здравствуйте, WFrag, Вы писали:


WF>>Здравствуйте, Octane, Вы писали:


O>>Вопросы:

O>>1)как описать оператор сложения TYPE и Complex ?(TYPE — левый операнд)
O>>2)как описать конверсию от типа TYPE к типу Complex?

UC>Прошу вас обратится к учебнику и посмотреть зачем нужен конструктор копирования.


Читай 11.3.5 Страуструпа. Пример один в один. Это не конструктор копирования, это конструктор для преобразования.

UC>Если:

UC>Complex C = 10.01;
UC>то тут нужен конструктор копирования.

Это не конструктор копирования.

UC>А если

UC>cout << C + 10.01 << endl;
UC>то перегрузка оператора. И ниакак без дружественной функции необойтись (если нужен double как левый операнд).

А зачем вообще тут дружественность? template прав, дружественность не нужна.

Complex
{
private:
    // ...
public:
    Complex( double num ) // Для конверсии от double к Complex, например, при передаче в функцию
    {
        // ...
    }
    
    const Complex& operator=( double num )    // Можно еще присваивание добавить
    {
        // ...
    }

    Complex operator+( double a ) const
    {
        // ...
    }
}

Complex operator+( double a, const Complex& b )
{
    return b + a; // и зачем тут дружественность?
}
7. О чем невозможно говорить, о том следует молчать.
Re[3]: Перегрузка операторов
От: WFrag США  
Дата: 05.05.03 00:08
Оценка:
Здравствуйте, Octane, Вы писали:

O>Здравствуйте, WFrag, Вы писали:


WF>>По-моему, конструктором:

O>
O>class Complex
O>{
O>private:
O>    ...
O>public:
O>    Complex( double num )
O>    {
O>    }
O>        ...
O>};
O>


O>Хм..с операторами всё отлично решилось а вот с конструкторами не очень, так можно описать только принудительную конверсию , а мне бы хотелось чтобы компилятор сам делал за меня эту грязную работу


Почему только принудительную?

class Complex 
{
public:
    Complex( double num )
    {
    }
}

// ...

double a = 1.234;
Complex c;

c = 123.5 + a; // Все OK, присваивание произойдет через конструирование временного объекта Complex(123.5+a), а потом оператор присваивания Complex& opearator=( const Complex& )


Глава 11.3.5 Страуструпа.
7. О чем невозможно говорить, о том следует молчать.
Re[4]: Перегрузка операторов
От: UltraCpp Ниоткуда ultra-cpp.narod.ru
Дата: 05.05.03 05:50
Оценка:
Здравствуйте, WFrag, Вы писали:

Я вот не совсем понимаю, как будет работать конструктор преобразования, если Complex это класс строк, и мне нужно "приклеить" double в начало char*??? Тут тоже без дружественной функции необойтись???
(см. "Структуры данных в С++" Уиллиям Топп, Уиллиям Форд).
Re: Перегрузка операторов
От: Bell Россия  
Дата: 05.05.03 06:33
Оценка:
Здравствуйте, Octane, Вы писали:

O>Итак... есть класс :


...

O>Вопросы:

O>1)как описать оператор сложения TYPE и Complex ?(TYPE — левый операнд)


class Complex
{
private:
    ...
public:
    ...
    const Complex operator+(const Complex &other){...}
    const Complex operator+(const double &other){...}
        ...
};

const Complex operator + (double lhs, const Complex& rhs) { return rhs + lhs; }

O>2)как описать конверсию от типа TYPE к типу Complex?

class Complex
{
public:
   Complex(TYPE arg) {...}
};

Однако такими преобразованиями нужно пользоваться очень осторожно, а лучше их вообще не использовать.
Любите книгу — источник знаний (с) М.Горький
Re[4]: Перегрузка операторов
От: Octane Россия  
Дата: 05.05.03 08:06
Оценка:
Здравствуйте, WFrag, Вы писали:

WF>Почему только принудительную?


class Complex 
{
public:
    Complex( double num )
    {
    }
}

// ...

double a = 1.234;
Complex c;

c = 123.5 + a; // Правая часть вычисляется получаем double который для присваивания может быть конвертирован только в Complex
c = c + a; // Все Bad, без перегрузки оператора + правая часть не сможет быть вычисленна
c = c + Complex(a); // Всё ОК, принудительная конверсия
Re[5]: Перегрузка операторов
От: Bell Россия  
Дата: 05.05.03 08:29
Оценка:
Здравствуйте, Octane, Вы писали:

А проверить хотя бы можно было?
Вот этот код компилится и работает:


class Complex 
{
public:
    Complex() {}
    Complex( double num )
    {
    }
const Complex operator + (const Complex& rhs) { return Complex(); }
};

int main()
{
double a = 1.234;
Complex c;

c = 123.5 + a; // Правая часть вычисляется получаем double, который затем конвертируется в Complex с 
// использоавнием констркуктора Complex::Complex (double), а затем полученный временный объект 
// присваиваивается объекту c с использованием operator=, сгенерированного компилятором
c = c + a; //Переменная a конвертируется в Complex с использоавнием констркуктора Complex::Complex (double),
// а затем вызывается Complex::operator+()
 c = c + Complex(a); // Всё ОК, принудительная конверсия
return 0;
}
Любите книгу — источник знаний (с) М.Горький
Re[3]: Перегрузка операторов
От: limax Эстония http://mem.ee
Дата: 05.05.03 08:32
Оценка:
Здравствуйте, template, Вы писали:
UC>class Complex
UC>{
UC> friend Complex operator+(int fst, const Complex &Snd); // лишнее (template)
UC>};
T>не согласен, friend тут излишество, вмешиваемся в чужой код. А так решение, лучше не придумаешь.

Какой же он лишний, если оператор определяется вместе с классом, но из-за недостатков С++ (или наоборот достоинства — кому как больше нравится) не может являться методом класса?
Have fun: Win+M, Ctrl+A, Enter
Re[4]: Перегрузка операторов
От: Bell Россия  
Дата: 05.05.03 08:38
Оценка:
Здравствуйте, limax, Вы писали:

L>Здравствуйте, template, Вы писали:

UC>class Complex
UC>{
UC> friend Complex operator+(int fst, const Complex &Snd); // лишнее (template)
UC>};
T>не согласен, friend тут излишество, вмешиваемся в чужой код. А так решение, лучше не придумаешь.

L>Какой же он лишний, если оператор определяется вместе с классом, но из-за недостатков С++ (или наоборот достоинства — кому как больше нравится) не может являться методом класса?


Нет никакой необходимости объявлять внешний operator+ как friend, т.к. он элементарно реализуется через "внутренний".
Любите книгу — источник знаний (с) М.Горький
Re[4]: Перегрузка операторов
От: template  
Дата: 05.05.03 08:40
Оценка:
Здравствуйте, limax, Вы писали:

L>Какой же он лишний, если оператор определяется вместе с классом

А кто Вам сказал что он должен быть обязательно определен вместе с классом:

Complex ooperator +  (Complex &a, Complex & b)
{
    Complex c(a.real() + b.real(), a.imag() + b.imag());
    return c;
}


вот Вам примерчик, я не лезу дальше паблик методов и меня абсолютно не должно волновать как устроен класс. И зачем тут friend????

Исправлена подсветка синтаксиса. -- ПК.
Re[5]: Перегрузка операторов
От: template  
Дата: 05.05.03 08:50
Оценка:
Здравствуйте, UltraCpp, Вы писали:

UC>Я вот не совсем понимаю, как будет работать конструктор преобразования, если Complex это класс строк, и мне нужно "приклеить" double в начало char*??? Тут тоже без дружественной функции необойтись???

UC>(см. "Структуры данных в С++" Уиллиям Топп, Уиллиям Форд).

Если есть Complex(double n) тогда вот примерчик

Complex operator + (double a, Complex &b)
{
    Complex c(a);
    c += b;
    return c;
}
Complex operator + (Complex &a, double b)
{
    Complex c(a);
    c += Complex(b);
    return c;
}


По-моему разрулили и как всегда не лезли в чужой код (обошлись без friend)

Исправлена подсветка синтаксиса. -- ПК.
Re[5]: Перегрузка операторов
От: limax Эстония http://mem.ee
Дата: 05.05.03 08:52
Оценка:
Здравствуйте, Bell, Вы писали:

B>Нет никакой необходимости объявлять внешний operator+ как friend, т.к. он элементарно реализуется через "внутренний".


В данном конкретном случае — да. Но не в общем случае, особенно если оператор некоммутативный (a+b != b+a).

Хотя и там разные приёмы есть, например конструирование анонимного экземпляра (return C(a)+c). Но повторяю, в общем случае это может быть не применимо, и дружественность может понадобиться.
Have fun: Win+M, Ctrl+A, Enter
Re[6]: Перегрузка операторов
От: Bell Россия  
Дата: 05.05.03 09:01
Оценка:
Здравствуйте, limax, Вы писали:

...

L>В данном конкретном случае — да. Но не в общем случае, особенно если оператор некоммутативный (a+b != b+a).

А речь и идет о "данном конкретном случае". Во всяком случае автор вопроса на спрашивал о том, как нужно реализовывать внешние операторы в общем случае, и никак не упоминал о том, что его operator+ некоммутативен
Любите книгу — источник знаний (с) М.Горький
Re[7]: Перегрузка операторов
От: limax Эстония http://mem.ee
Дата: 05.05.03 09:05
Оценка:
Здравствуйте, Bell, Вы писали:

L>В данном конкретном случае — да. Но не в общем случае, особенно если оператор некоммутативный (a+b != b+a).

B>А речь и идет о "данном конкретном случае". Во всяком случае автор вопроса на спрашивал о том, как нужно реализовывать внешние операторы в общем случае, и никак не упоминал о том, что его operator+ некоммутативен
B>

Убедил
А то я уже хотел пример искать, где без friend не обойтись.
Have fun: Win+M, Ctrl+A, Enter
Re[6]: Перегрузка операторов
От: Octane Россия  
Дата: 05.05.03 11:43
Оценка:
Здравствуйте, Bell, Вы писали:

B>А проверить хотя бы можно было?

B>Вот этот код компилится и работает:

Хм..был неправ,извиняюсь.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.