Перегрузка операторов в C ++ - PullRequest
       19

Перегрузка операторов в C ++

1 голос
/ 07 сентября 2011

Мне нужно перегрузить оператор * в C ++.Поэтому я создал класс с именем Element, который должен перегружать этот оператор, чтобы он работал с двойным значением, хранящимся в нем.Вот что я сделал в файле реализации:

#include "Element.h"
#include <iostream>

using namespace std;

// Other code that is not relevant

Element Element::operator * ( const Element &obj)
{
    d *= obj.d;
    return *this;
}

Это не работает.Выдает ошибку, говорящую: «нет совпадения для« оператора * »в« 8 * с »

В основном файле у меня есть:

d = a = 8 * c - 4 + b;

где d, a, c и bвсе объекты класса Элемент

Ответы [ 5 ]

3 голосов
/ 07 сентября 2011

Вы действительно должны понимать, что вы здесь делаете, вы перегружаете оператор '*' для класса Element, но вы делаете это, ожидая, что у другого элемента есть «параметр».

код, который вы написали, на самом деле ожидает такой код

Element v, w, a;
a = v * w;

Как уже упоминалось, вы можете взглянуть на: http://www.learncpp.com/cpp-tutorial/92-overloading-the-arithmetic-operators/

1 голос
/ 07 сентября 2011

Вы можете сопоставить выражение 8 * c (int, Element) с перегрузкой, не являющейся членом, например

Element operator* (const Element& leftHandSide, const Element& rightHandSide){
   return Element( leftHandSide.d * rightHandSide.d);
}

Используя const Element&, вы можете использовать конструктор с сигнатурой, такой как Element::Element(int ) для преобразования типов.

1 голос
/ 07 сентября 2011

потому что вы перегружаете оператор * только для Element * Element, а для c * 8 вам придется реализовать Element Element::operator * ( const int i)

0 голосов
/ 07 сентября 2011

У меня есть решение для вас и предупреждение о перегрузке вашего оператора.

Решение:

#include <iostream>
using namespace std;

struct Element {
    double d;
    Element(double d) {this->d = d;}
    Element operator*(const Element &obj) {
        d *= obj.d;
        return *this;
    }
};

Element operator*(const int i, const Element& e) {
    return Element(static_cast<double>(i) * e.d);
}

ostream& operator<<(ostream& os, const Element& e) {
    os << e.d;
    return os;
}

int main() {
        Element e(2);
        cout << "Product of 8 and e: " << 8*e << '\n';

        // This shows why your overload is a bad idea:
        Element a(3);
        cout << "a is " << a << '\n'; // prints 3
        cout << "Now its product with e is: " << a*e << '\n'; // prints 6
        cout << "Surprise: a is now " << a << '\n'; // prints 6
}

Ваша первоначальная перегрузка не сработала, потому что она даже не вызывалась. Ваше выражение было похоже на

a = 8*c

, где 8 имеет тип int, и когда C ++ анализирует это выражение слева направо, он видит, что 8 имеет тип int, и пытается найти перегрузку оператора * (const Element &) в типе int, и он не может найти его потому что он не знает и не должен ничего знать о вашем собственном определяемом пользователем типе. Поэтому, если вы хотите, чтобы ваш собственный класс взаимодействовал с другими типами, вам нужно либо встроить перегрузку оператора * как функции-члена в этот другой тип, либо объявить его как внешнюю функцию, как я делал в своем решении.

Теперь предупреждение. Ваша первоначальная перегрузка оператора плохо определена, потому что она изменяет исходный объект, что считается неожиданным поведением. Я показываю это в коде выше. Это как умножение 8 на 2 даст вам 16, но в то же время получится 16 из ваших 8. Что вы действительно хотите сделать, так это создать новый элемент в вашем операторе умножения и вернуть его:

struct Element {
    double d;
    Element(double d) {this->d = d;}
    Element operator*( const Element &obj) {
        return Element(this->d * obj.d);
    }
};

Черт, эти ответы занимают много времени ... Я должен работать, хотя: \

0 голосов
/ 07 сентября 2011

Ваша существующая реализация оператора позволяет умножить два Element объекта вместе. Но, согласно клиентскому коду в вашем «главном файле», вы должны быть в состоянии умножить объект Element на скалярное значение; 8 в этом случае.

Итак, вам нужен дополнительный оператор, в качестве параметра которого используется double: Примерно так:

Element Element::operator * ( const double scalar ) const
{
    const Element e( d * scalar );
    return e;
}

Здесь я предполагаю, что ваш класс Element имеет конструктор, который принимает один скалярный параметр и присваивает его d.

Обратите внимание, что ваша существующая реализация оператора * семантически странна, поскольку он мутирует внутреннее состояние d (с * =). Это почти наверняка не то, что вы хотите ...

...