我們在上一節介紹了關於重載和友元的概念和用法!這篇文章重點介紹運算符重載的一些實例。
上篇我們已經說了,運算符重載相當於賦予運算符”拓展功能”。所以並不侷限於“加減乘除”等。我們在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
建議仔細閱讀並理解其中的邏輯關係,以及運算符重載在此類問題中發揮的作用!