void main(void)
{
Complex z(1,2);
z=z+1;/* все работает */
z=3+z;/* Нет такого глобального оператора или нет соответствующей заданным операторам конверсии*/
}
Вопросы:
1)как описать оператор сложения TYPE и Complex ?(TYPE — левый операнд)
2)как описать конверсию от типа TYPE к типу Complex?
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
}
Здравствуйте, WFrag, Вы писали:
WF>По-моему, конструктором:
class Complex
{
private:
...
public:
Complex( double num )
{
}
...
};
Хм..с операторами всё отлично решилось а вот с конструкторами не очень, так можно описать только принудительную конверсию , а мне бы хотелось чтобы компилятор сам делал за меня эту грязную работу
Здравствуйте, WFrag, Вы писали:
WF>Здравствуйте, Octane, Вы писали:
O>Вопросы: O>1)как описать оператор сложения TYPE и Complex ?(TYPE — левый операнд)
WF>Глобальный оператор: WF>
Прошу вас обратится к учебнику и посмотреть зачем нужен конструктор копирования.
Если:
Complex C = 10.01;
то тут нужен конструктор копирования.
А если
cout << C + 10.01 << endl;
то перегрузка оператора. И ниакак без дружественной функции необойтись (если нужен double как левый операнд).
Здравствуйте, 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. О чем невозможно говорить, о том следует молчать.
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. О чем невозможно говорить, о том следует молчать.
Я вот не совсем понимаю, как будет работать конструктор преобразования, если Complex это класс строк, и мне нужно "приклеить" double в начало char*??? Тут тоже без дружественной функции необойтись???
(см. "Структуры данных в С++" Уиллиям Топп, Уиллиям Форд).
Здравствуйте, 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); // Всё ОК, принудительная конверсия
А проверить хотя бы можно было?
Вот этот код компилится и работает:
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;
}
Здравствуйте, template, Вы писали: UC>class Complex UC>{ UC> friend Complex operator+(int fst, const Complex &Snd); // лишнее (template) UC>}; T>не согласен, friend тут излишество, вмешиваемся в чужой код. А так решение, лучше не придумаешь.
Какой же он лишний, если оператор определяется вместе с классом, но из-за недостатков С++ (или наоборот достоинства — кому как больше нравится) не может являться методом класса?
Здравствуйте, limax, Вы писали:
L>Здравствуйте, template, Вы писали: UC>class Complex UC>{ UC> friend Complex operator+(int fst, const Complex &Snd); // лишнее (template) UC>}; T>не согласен, friend тут излишество, вмешиваемся в чужой код. А так решение, лучше не придумаешь.
L>Какой же он лишний, если оператор определяется вместе с классом, но из-за недостатков С++ (или наоборот достоинства — кому как больше нравится) не может являться методом класса?
Нет никакой необходимости объявлять внешний operator+ как friend, т.к. он элементарно реализуется через "внутренний".
Здравствуйте, limax, Вы писали:
L>Какой же он лишний, если оператор определяется вместе с классом
А кто Вам сказал что он должен быть обязательно определен вместе с классом:
Здравствуйте, 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)
Здравствуйте, Bell, Вы писали:
B>Нет никакой необходимости объявлять внешний operator+ как friend, т.к. он элементарно реализуется через "внутренний".
В данном конкретном случае — да. Но не в общем случае, особенно если оператор некоммутативный (a+b != b+a).
Хотя и там разные приёмы есть, например конструирование анонимного экземпляра (return C(a)+c). Но повторяю, в общем случае это может быть не применимо, и дружественность может понадобиться.
...
L>В данном конкретном случае — да. Но не в общем случае, особенно если оператор некоммутативный (a+b != b+a).
А речь и идет о "данном конкретном случае". Во всяком случае автор вопроса на спрашивал о том, как нужно реализовывать внешние операторы в общем случае, и никак не упоминал о том, что его operator+ некоммутативен
Здравствуйте, Bell, Вы писали:
L>В данном конкретном случае — да. Но не в общем случае, особенно если оператор некоммутативный (a+b != b+a). B>А речь и идет о "данном конкретном случае". Во всяком случае автор вопроса на спрашивал о том, как нужно реализовывать внешние операторы в общем случае, и никак не упоминал о том, что его operator+ некоммутативен B>
Убедил
А то я уже хотел пример искать, где без friend не обойтись.