運算符重載典例:Vector-維克多

  我們在上一節介紹了關於重載和友元的概念和用法!這篇文章重點介紹運算符重載的一些實例。
  上篇我們已經說了,運算符重載相當於賦予運算符”拓展功能”。所以並不侷限於“加減乘除”等。我們在C++中,使用打印函數時,常常用count<<來表示,但我們也知道<<,也可以表示“移位”!這裏其實就是對<<做了“運算符重載”!我們也知道,當要輸出類Time對象coding的hours,minutes值時,我們必須寫成這樣:

void Time::Show() const
{
    std::cout << hours << " hours, " << minutes << " minutes";
}
coding.Show();

但我們有沒有一種辦法,直接輸出

cout<<coding

以表示我們輸出的是coding的變量呢?
所以可以在類裏定義下面的函數:
void operator<<(ostream & os)
但是我們知道的是:運算符左邊必須是成員對象,即理論上我們必須寫爲:

coding<<cout

然而顯然,這種寫法是彆扭的!
所以這裏祭出我們的

friend std::ostream & operator<<(std::ostream & os, const Time & t);
std::ostream & operator<<(std::ostream & os, const Time & t)
{
    os << t.hours << " hours, " << t.minutes << " minutes";
    return os; 
}

從而,我們可以這樣使用

 cout << aida<<"; " << tosca << endl;

這是第一個例子!我們接下來介紹與標題相符的例子:向量的運算
向量的運算
  我們都知道當我們計算向量A+向量B時,其實並不是直接x相加,因爲我們要考慮一個向量的長度和角度,所以我們通常先算出它的垂直和水平分量,然後再直接想加!也就是說這裏的“+”號,已經超出了“程序”所能解釋的計算細節,所以對於向量的計算,我們有必要拓展一下“+”號的功能!爲了能夠更好的拓展程序思想,我們舉個實例:在C++ primer plus中,稱之爲“醉漢問題!即醉漢在路燈下以固定步長隨機向四周遊走,問多少步後離路燈50米!這裏很顯然涉及“向量”的運算問題,當然我們也可以設計成隨機步長,但這並沒有什麼實質性的不同,僅僅”固定步長+隨機方向”就已經能說明問題了!
如上面所說,我們計算向量的加法,實際上是先換算成“垂直分量”和“豎直分量”!所以我們很容易的想到下面的方法!

void Vector::set_x()
    {
        x = mag * cos(ang);
    }

// set y from polar coordinate
void Vector::set_y()
    {
        y = mag * sin(ang);
    }
Vector::Vector()             // default constructor
    {
        x = y = mag = ang = 0.0;
        mode = RECT;
    }

    // construct vector from rectangular coordinates if form is r
    // (the default) or else from polar coordinates if form is p
Vector::Vector(double n1, double n2, Mode form)
    {
        mode = form;
        if (form == RECT)
         {
             x = n1;
             y = n2;
             set_mag();
             set_ang();
        }
        else if (form == POL)
        {
             mag = n1;
             ang = n2 / Rad_to_deg;
             set_x();
             set_y();
        }
        else
        {
             cout << "Incorrect 3rd argument to Vector() -- ";
             cout << "vector set to 0\n";
             x = y = mag = ang = 0.0;
             mode = RECT;
        }
    }

注意,程序爲了適應不同的輸入規則,設定了一個狀態量:mode
這只是拓展功能,對我們理解“運算符重載”沒有關聯,但事實上,我們仍需要掌握這種“狀態量”的使用方法!
這樣我們運算符重載的函數方法可以寫成這樣

 Vector Vector::operator+(const Vector & b) const
    {
        return Vector(x + b.x, y + b.y);
    }

    // subtract Vector b from a
    Vector Vector::operator-(const Vector & b) const
    {
        return Vector(x - b.x, y - b.y);
    }

    // reverse sign of Vector
    Vector Vector::operator-() const
    {
        return Vector(-x, -y);
    }

    // multiply vector by n
    Vector Vector::operator*(double n) const
    {
        return Vector(n * x, n * y);
    }

    // friend methods
    // multiply n by Vector a
    Vector operator*(double n, const Vector & a)
    {
        return a * n;
    }

    // display rectangular coordinates if mode is RECT,
    // else display polar coordinates if mode is POL
    std::ostream & operator<<(std::ostream & os, const Vector & v)
    {
        if (v.mode == Vector::RECT)
             os << "(x,y) = (" << v.x << ", " << v.y << ")";
        else if (v.mode == Vector::POL)
        {
             os << "(m,a) = (" << v.mag << ", "
                 << v.ang * Rad_to_deg << ")";
        }
        else
             os << "Vector object mode is invalid";
        return os; 
    }

完整的程序請查看我上傳的c++ primer plus 源碼第11章,vector.cpp
建議仔細閱讀並理解其中的邏輯關係,以及運算符重載在此類問題中發揮的作用!

發佈了50 篇原創文章 · 獲贊 150 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章