Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Перегрузка операторов


Автор: Salatovec 5.8.2014, 14:36
Всем привет. Такой вопрос - если написать так:
Код

class MyVector
{
public:
    double x, y, z;

    MyVector operator * (double c)
    {
        MyVector res;
        res.x *= c;
        res.y *= c;
        rez.z *= c;
        return res;
    }
};

void main()
{
    double some_value;
  
    MyVector some_vector; 
}

То так 
Код

some_vector*some_value
 
работает, а так 
Код

some_value*some_vector
 
нет.

Как быть?

Автор: baldina 5.8.2014, 14:52
Код

class MyVector
{
public:
    double x, y, z;
    MyVector& operator *= (double c)
    {
        x *= c;
        y *= c;
        z *= c;
        return *this;
    }
};

MyVector operator*(const MyVector &v, double c) {
  MyVector temp(v);
  temp *= c;
  return temp;
}

MyVector operator*(double c, const MyVector &v) {
  return v*c; // using MyVector operator*(const MyVector &v, double c)
}



Добавлено через 3 минуты и 16 секунд
http://ideone.com/ozFc6x

Автор: Salatovec 5.8.2014, 15:03
baldina, компилятор ругается на "operator CVertex::*(const CVertex &,double)' must be declared with one parameter".

Автор: baldina 5.8.2014, 15:05
и? ни в моем, ни в приведенном вами коде нет CVertex

Добавлено через 29 секунд
скорее всего в классе у вас объявление с одним числом параметров, а определение вне класса - сдругим

Добавлено через 1 минуту и 16 секунд
и еще: я вам привел примеры операторов - свободных функций. не надо их пихать в класс

Добавлено через 2 минуты и 32 секунды
посмотрите на работающий пример и подумайте. будут вопросы - задавайте. пока не поймете для чего каждая строчка, дальше не двигайтесь

Автор: EnergoHokum 6.8.2014, 14:36
Оператор умножения перегружен для класса MyVector, поэтому вариант, "где работает", можно переписать так:
Код

some_vector.operator * (some_value);

Разумеется, для системного типа double перегрузки оператора умножения по умолчанию нет, потому конпелятор и возмущается. Выход тут такой: написать свободную (не привязанную к какому либо классу) функцию перегрузки оператора умножения, которая первым параметром принимает double, а вторым -- требуемый класс. Разумеется, должен быть смысл в умножении числа на класс, например, перегрузив оператор умножения для числа и std::string, получим бессмыслицу: абсолютно неясно, что должно быть возвращено. Строка, повторенная несколько раз? А если умножаем не на целое? 3.1415 строки -- это сколько? Но это я уже отвлёкся. В данном случае будет логично вернуть объект класса MyVector, для которого xy и [bz[/b] будут равны xy и [bz[/b] второго входного параметра (some_vector), умноженным каждый на первый входной параметр (some_value):
Код

MyVector operator * (double in_some_value, MyVector in_some_vector)
{
    return in_some_vector * in_some_value; /* Раз уж перегрузили оператор умножения для класса -- так и воспользуемся им, in_some_vector всего лишь копия, оригинал не изменится */
}

Автор: Lukkoye 6.8.2014, 23:38
http://rextester.com/VMWGW49228


Код

#include <iostream>

class MyVector
{
public:
    double x, y, z;
    MyVector operator * (double c)const
    {
        MyVector res;
        res.x *= c;
        res.y *= c;
        res.z *= c;
        return res;
    }
    friend MyVector operator*(const double c, const MyVector& v) 
    {
      return v*c;
    }
};

int main()
{
    std::cout << "Hello, world!\n";
    
    double some_value;
  
    MyVector some_vector; 
    
    some_vector * some_value;
    some_value * some_vector;
}

Автор: kLASTER 11.8.2014, 06:03
Текст вырван из книги, но как мне кажется полностью отвечает на вопрос.
Пример:

Помните, что левый операнд — это  
вызывающий объект. То есть 

А = В * 2.75; 

транслируется в следующий вызов функции-члена: 

А = В.operator* (2.75); 

Но как насчет приведенного ниже оператора? 

А = 2.75 * В; // не соответствует функции-члену 

Концептуально 2.75 * В должно быть эквивалентно В * 2 . 7 5, но первое  выражение не может соответствовать функции-члену, поскольку 2.75 не является объектом типа Time. Помните, что левый операнд — это вызывающий объект, но 2 . 75 — не  объект. Поэтому компилятор не может заменить это выражение вызовом функции-члена. Один из способов обойти эту трудность — сказать всем (и запомнить самому), что допускается только запись в виде В * 2.75, но не 2.75 * В. Это дружественное к серверу решение, возлагающее ответственность на клиента, что не отвечает принципам ООП. Однако существует другая возможность — использовать функцию, не являющуюся членом. (Вспомните, что большинство операций могут быть перегружены с  применением как функций-членов, так и просто функций.) Функция, не являющаяся членом, не вызывается через объект. Вместо этого все значения, которые она использует, включая объекты, передаются в виде явных аргументов. Таким образом, компилятор может представить выражение 

А = 2.75 * В; //не соответствует функции-члену 

в виде вызова функции, не являющейся членом: 

А = operator* (2.75, В); 

Эта функция должна иметь следующий прототип: 
Time operator* (double m, const Time & t) ; 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)