بخش ۹ - سربارگذاری عملگرها

در این بخش مباحثی پیرامون سربارگذاری عملگرها مطرح می‌شوند. علاوه بر سربارگذاری عملگرهای ساده مانند + و =+، عملگر درج در جریان‌های خروجی نیز سربارگذاری می‌شود. علاوه بر مباحث مربوط به سربارگذاری عملگرها، توابع عضو ثابت و همچنین توابع دوست نیز مورد اشاره قرار می‌گیرند. مثال‌های این بخش پیاده‌سازی یک تایپ برای اعداد مختلط هستند.

فهرست مثال‌ها

اعداد مختلط بدون سربارگذاری عملگرها

در این بخش کلاس Complex برای استفاده از اعداد مختلط تعریف می‌شود. اعمال جمع و افزایش از طریق متدهای عادی قابل اعمال روی اعداد هستند.

01_ComplexNonOverload.cpp
#include <iostream>
using namespace std;

class Complex {
public:
    Complex(double r, double i) : real(r), imag(i) {}
    Complex(double r) : real(r), imag(0) {}
    void print() const;

    Complex add(const Complex& c) const;
    void inc(const Complex& c);

    double re() const { return real; }
    double im() const { return imag; }
private:
    double real;
    double imag;
};

Complex Complex::add(const Complex& c) const {
    return Complex(real + c.real, imag + c.imag);
}

void Complex::inc(const Complex& c) {
    real += c.real;
    imag += c.imag;
}

void Complex::print() const {
    cout << real;
    if (imag > 0)
        cout << '+' << imag << 'i';
    else if (imag < 0)
        cout << imag << 'i';
}

int main() {    
    Complex a(1, 2);
    Complex b(4, -2);

    const Complex zero(0,0);
    zero.inc(a);    // compile error
    zero.print();   // OK!

    a.print();          // 1+2i
    b.print();          // 4-2i

    Complex c = a.add(b);
    c.print();          // 5
    
    b.inc(c);           // 9-2i
    b.print();
}
				
سربارگذاری عملگرهای + و =+

در این بخش، دو عملگر + و =+ برای کلاس اعداد مختلط سربارگذاری می‌شوند. با داشتن این عملگرها، این کلاس به شکل خواناتر و راحت‌تری قابل استفاده است.

02_ComplexAddInc.cpp
class Complex {
public:
//  Complex add(const Complex& c) const;
    Complex operator+(const Complex& c) const;
//  void inc(const Complex& c);
    Complex& operator+=(const Complex& c);

};

//Complex Complex::add(const Complex& c) const
Complex Complex::operator+(const Complex& c) const
{
    return Complex(real + c.real, imag + c.imag);
}

//void Complex::inc(const Complex& c)
Complex& Complex::operator+=(const Complex& c)
{
    real += c.real;
    imag += c.imag;
    return *this;
}

int main()
{
    Complex a(1, 2);
    Complex b(4, -2);

    // Complex c = a.add(b);
    Complex c = a + b;
    c.print();          // 5
    
    // b.inc(c);            
    b += c;     
    b.print();          // 9-2i
    b.operator+(c);

    (b += c).print();
}
				
سربارگذاری عملگرهای + برای جمع با یک عدد حقیقی

در این بخش، عملگر + برای جمع یک عدد مختلط با یک عدد حقیقی سربارگذاری شده است. به این ترتیب، می‌توان عباراتی مانند c + 2.5 داشت که در آن c یک عدد مختلط است.

03_ComplexAddDouble.cpp
class Complex {
public:
    Complex operator+(double r) const;
};

Complex Complex::operator+(double r) const
{
    return Complex(real + r, imag);
}

int main()
{
    Complex a(1, 2);

    Complex c = a + 2;
    c.print();            // 3+2i 
}
				
عملگر + در حالی که سمت چپ آن عدد حقیقی است

در این بخش، عملگر + برای جمع یک عدد مختلط با یک عدد حقیقی سربارگذاری شده است. به این ترتیب، می‌توان عباراتی مانند 2.5 + c داشت که در آن c یک عدد مختلط است.

04_ComplexAddDouble.cpp

Complex operator+(const double r, const Complex& c)
{
	return Complex(c.re() + r, c.im());
}

int main()
{
    Complex a(1, 2);

    Complex c = 2 + a;
    c.print();            // 3+2i 
}
				
عملگر >> برای درج در خروجی

در این بخش، عملگر >> برای درج یک عدد مختلط در یک جریان خروجی سربارگذاری می‌شود.

05_ComplexInsertion.cpp

ostream& operator<<(ostream& out, const Complex& c)
{
    out << c.re();
    if (c.im() > 0)
        out << '+' << c.im() << 'i';
    else if (c.im() < 0)
        out << c.im() << 'i';
        
    return out;
}

int main()
{
    Complex a(1, 2);
    Complex b(4, -2);

    cout << a << b << endl;
}
				
توابع دوست

در این بخش، عملگر >> به عنوان دوست کلاس Complex تعریف می‌شود و در نتیجه می‌تواند به اعضای خصوصی این کلاس دسترسی داشته باشد. طبیعتاً چنین کاری برخلاف اصول برنامه‌نویسی شیءگرا است و مخفی‌سازی اطلاعات را زیر سؤال می‌برد. به همین دلیل استفاده از این امکان جز در موارد خاص توصیه نمی‌شود. یکی از این موراد سربارگذاری عملگر >> است.

06_ComplexFriend.cpp
class Complex {
    friend ostream& operator<<(ostream& out, const Complex& c);
};

ostream& operator<<(ostream& out, const Complex& c)
{
    out << c.real;
    if (c.imag > 0)
        out << '+' << c.imag << 'i';
    else if (c.imag < 0)
        out << c.imag << 'i';

    return out;
}