претоварване на оператори и функции, които не са членове c++

Написах клас за комплексни числа, в който претоварих оператора + и всичко работи добре, но трябва да внедря това като функция, която не е член и не съм сигурен как или защо има полза от това.

Ето моят код .h:

class Complex
{
private:
    double a;
    double b;

public:
    Complex();
    Complex(double aGiven);
    Complex(double aGiven, double bGiven);

    double aGetValue();
    double bGetValue();    
    double operator[](bool getB);

    Complex add(Complex &secondRational);
    Complex operator+(Complex &secondRational);
}

.cpp:

Complex Complex::add(Complex &secondRational)
{
    double c = secondRational.aGetValue();
    double d = secondRational.bGetValue();
    double anew = a+c;
    double bnew = b+d;
    return Complex(anew,bnew);
}

Complex Complex::operator+(Complex &secondRational)
{
    return add(secondRational);
}

Всяка помощ за това как да ги направите като функции, които не са членове, ще бъде високо оценена!


person user906357    schedule 09.10.2013    source източник
comment
възможен дубликат на Претоварване на оператор   -  person Xeo    schedule 10.10.2013
comment
Трябва да прочетете за const. Много спешно.   -  person sbi    schedule 10.10.2013


Отговори (4)


Ето оператора за добавяне извън класа:

Complex operator+(const Complex& lhs, const Complex& rhs) {
  //implement the math to add the two
  return Complex(lhs.aGetValue() + rhs.aGetValue(),
                 lhs.bGetValue() + rhs.bGetValue());
}

Разбира се, ще трябва да декларирате aGetValue() и bGetValue() като const:

double aGetValue() const {return a;}
double bGetValue() const {return b;}
person pippin1289    schedule 09.10.2013

Можете да декларирате приятел във вашия Complex клас

class Complex {

// blah....

    friend Complex operator+(Complex const& a, Complex const & b);
};

Претовареният оператор има достъп до частните членове на Complex.

person CS Pei    schedule 09.10.2013

Обичайният подход към аритметичните операции е да се дефинират рефлексивните версии на операторите като членове и чистите версии като не-членове, като се имплементират с рефлексивните версии:

class complex {
public:
    const complex& operator+=(const complex& rhs) {
        real += rhs.real;
        imag += rhs.imag;
        return *this;
    }
};

complex operator+(const complex& lhs, const complex& rhs) {
    complex res(lhs);
    res += rhs;
    return res;
}
person Pete Becker    schedule 09.10.2013
comment
@DanielFrey - почти го направих, но реших, че е твърде объркващо. - person Pete Becker; 10.10.2013
comment
Сега успя да ме объркаш. Защо мислите, че би било объркващо? Имайки предвид, че int i = 0; (i+=1)+=2; е законно за интегрални типове, защо да не е законно за UDT? - person Daniel Frey; 10.10.2013
comment
@DanielFrey - (i+=1)+=2; е объркващо. <g> i += 1 + 2; е много по-добре. - person Pete Becker; 10.10.2013
comment
Добре, не мога да споря с това :) (не че ще приема този стил, но ще приема, че в този случай са възможни и други мнения. Също така: i+=j+k не е по-добро за UDT, тъй като ще създаде временен и по този начин той е по-малко ефективен). - person Daniel Frey; 10.10.2013
comment
@DanielFrey: искаш да кажеш, че изразите i + j + k сега са по-трудни за оптимизиране, отколкото ако += се връща чрез неконстантна препратка? Освен това, мисля, че do as ints е важно в генеричния код и трябва да има предимство пред забраната на потребителите да пишат неясен код. - person TemplateRex; 10.10.2013
comment
@DanielFrey - Не се притеснявам от допълнителен обект от тип complex. - person Pete Becker; 10.10.2013
comment
Съжалявам, но трябва да гласувам против него, защото е изненадващо за всеки, който пише тънка обвивка около вградена, която случайно използва верижно присвояване (въпреки че съм съгласен, че това е неясен код). Ако искате да популяризирате неканонична версия с препратка към const, мисля, че това трябва да се направи като коментар или отговор на каноничен въпрос. - person TemplateRex; 10.10.2013
comment
@TemplateRex Временните не са голяма работа, ако обектите са малки, Complex тук има само две двойни. Но работех с Complex<T> и T беше персонализиран тип с висока точност на базата 10. Или помислете за матрици. Тук става важно да се избягват временните елементи и защо библиотеки като моите df.operators се опитват да ги избягват. И това е и причината, IMHO, да позволите на потребителите да пишат глупави неща като (i+=j)+=k;. Да, разумен човек би използвал i+=j; i+=k;, но опитът ми казва, че не мога да приема разумно поведение от другите по всяко време :-) - person Daniel Frey; 10.10.2013
comment
@DanielFrey Мисля за големи std::bitset обекти със сложни логически изрази. - person TemplateRex; 10.10.2013
comment
@TemplateRex Друг добър пример, при който i&=j; i|=k; може да е по-малко ефективен, тъй като оптимизаторът може да не е в състояние да премине през паметта само веднъж сега в сравнение с (i&=j)|=k. Очевидно всичко това е настроение, без да го измерваме. Имайки предвид вашия вот против: може да го балансирате с отговора на Pete, който е единственият, който насърчава + да бъде внедрен с +=. - person Daniel Frey; 10.10.2013
comment
@DanielFrey се съгласи с +=, но тъй като това е като четворната измама на +500 Въпроси и отговори, мисля, че изобщо не трябваше да получава никакъв отговор. - person TemplateRex; 10.10.2013
comment
@TemplateRex - значи гласувате против моя отговор, защото смятате, че въпросът е трябвало да бъде затворен като дубликат? Това няма смисъл. - person Pete Becker; 10.10.2013
comment
@PeteBecker не, измамата беше странична забележка. Гласувах против const ref, защото е различно от вграденото поведение и стандартната библиотечна практика и е много възможно песимизиране на производителността. - person TemplateRex; 10.10.2013
comment
@TemplateRex - не можете да видите гората за дърветата. - person Pete Becker; 10.10.2013
comment
@PeteBecker, извинете, как подобни коментари ще ми помогнат да видя това, което смятате за толкова очевидно? Дадох 2 imho законни причини за гласуване против и вие не отговорихте на нито една от тях. - person TemplateRex; 10.10.2013
comment
T x; T& y = (x += 1); трябва да е валиден. Не защото искам да го използвам, а защото нямате основателна причина да ми попречите да го направя. Край на историята! - person Lightness Races in Orbit; 10.10.2013
comment
Правете както целите правят е много основно правило за претоварване на оператора и Случайно съм съгласен с това. Този клас operator+=() нарушава това правило. - person sbi; 10.10.2013
comment
(+1 все още е добър отговор, коригирайте в противен случай и между другото е най-добрият) - person Lightness Races in Orbit; 10.10.2013

Как е обяснено по-горе от pippin1289.

Защо е обяснено по-долу:

Представете си, че трябва да използвате обект от клас като

Complex c3 = 5 + c1;// for c3 object c1's real part (a) added with 5

Тъй като C++ запазва реда на операндите. Компилаторът разрешава горното допълнително извикване като 5.operator+ (const Complex & other);// което не е възможно. Следователно го претоварете чрез безплатна функция.

Вашият клас излага необходимата информация чрез публичен интерфейс като aGetValue() и bGetValue. Следователно, тази безплатна претоварена функция + оператор не трябва да бъде приятел на класа.

Освен това, предпочитайте не-приятелска нечленуваща функция пред членска функция, тъй като помага за намаляване на степента на капсулиране. Това е обяснено тук ==> http://www.drdobbs.com/cpp/how-non-member-functions-improve-encapsu/184401197?pgno=1

person sidd.rane    schedule 03.10.2015