1. 程式人生 > >操作符過載 之 輸出操作符"

操作符過載 之 輸出操作符"

操作符過載 之 輸出操作符”<<”(C++)

  • 問題背景
  • 技術推演
  • 解決方案
  • 總結

閱讀之前注意:

本文閱讀建議用時:30min
本文閱讀結構如下表:

專案 下屬專案 測試用例數量
問題背景 0
技術推演 2
解決方案 2
總結 0

問題背景

在C++中,我們自己定義了一個類,但我們卻不能用cout來直接輸出這個自定義類的具體物件。你可以試一試,編譯器會報錯的,這主要是因為編譯器不知道該按照什麼方式來輸出你自定義的類。
那我們就想用cout來直接輸出呢?怎麼辦呢?哈哈,我們有利器——操作符過載!這樣我們就可以規定輸出方式,有了規則,編譯器看到我們的這個類的物件就知道怎麼輸出了。

技術推演1

首先我們要承認的是,C++是把操作符過載用函式來實現的2

比如我們要實現下面的自定義類A的物件的加法,該怎麼做呢?自然能夠想到的,就是用函式來把物件中的每個成員變數做加法,參考以下程式碼:

#include"iostream"
using namespace std;

class A{
public:
    A(int a = 0, int b = 0)//使用預設引數,這樣既是有參建構函式,也是預設建構函式
    {
        this->a = a;
        this->b = b;
    }
public://為了方便起見,設定為public
int a; int b; }; A addA(A &A1,A &A2)//實現物件加法的函式 { A tmp; tmp.a = A1.a + A2.a; tmp.b = A1.b + A2.b; return tmp; } void main() { A a1(1, 2), a2(3, 4); A a3 = addA(a1, a2);//用函式來做物件的加法 cout << "a" << a3.a << " b" << a3.b << endl; system("pause"
); }

接下來我們看看操作符過載是怎麼用函式實現的:

#include"iostream"
using namespace std;

class A{
public:
    A(int a = 0, int b = 0)//使用預設引數,這樣既是有參建構函式,也是預設建構函式
    {
        this->a = a;
        this->b = b;
    }
public://為了方便起見,設定為public
    int a;
    int b;
};

A operator+(A &A1,A &A2)//操作符過載
{
    A tmp;//這裡會呼叫預設建構函式
    tmp.a = A1.a + A2.a;
    tmp.b = A1.b + A2.b;
    return tmp;
}

void main()
{
    A a1(1, 2), a2(3, 4);
    A a4 = operator+(a1, a2);
    A a5 = a1 + a2;
    cout << "a" << a4.a << " b" << a4.b << endl;
    cout << "a" << a5.a << " b" << a5.b << endl;
    system("pause");
}

上面程式碼中是用全域性函式來實現操作符過載,事實上這並不是正規寫法,但為了方便理解,正不正規姑且不論。在main函式中,我們可以看到語句“A a4 = operator+(a1, a2);”和語句“A a5 = a1 + a2;”的效果都是一樣的。
因此我們可以推測,C++編譯器在看到自定義型別在做加法時,也就是看到+號,它會自動的呼叫過載函式,把左操作物件(+號左邊的物件)和右操作物件(+號右邊的物件)分別傳入過載函式。這樣一來,我們就知道C++確實是把操作符過載用函式來實現的。

解決方案

思路:根據以上的技術推演,我們可以同樣的應用在“<<”操作符上,那麼這個操作符過載的話,需要什麼引數呢?毫無疑問,我們自定義型別的物件的引數需要傳進去。
我們先看看以下程式碼:

#include"iostream"
using namespace std;

void main()
{
    int a = 10;
    char *b = "hello, world";
    cout << a;
    cout << b;
    system("pause");
}

可以看到,基礎的型別(也就是int和字串指標型別)作為了引數,但還有一個引數,看來看去,就只有cout了=-=,哈哈,想不到吧,cout竟然也是一個引數。
其實如果我們右鍵檢視一下cout,就能看到下面圖片中的內容
cout
看到了吧,cout前面帶著一個型別說明符“ostream”,即cout也是一個類的物件。
這樣我們就知道過載”<<”需要哪些引數了:一個是ostream型別的物件,還有一個就是我們自定義型別A的物件。
下面我們就來實現它!
參考以下程式碼:

#include"iostream"
using namespace std;

class A{
public:
    A(int a = 0, int b = 0)//使用預設引數,這樣既是有參建構函式,也是預設建構函式
    {
        this->a = a;
        this->b = b;
    }
public://為了方便起見,設定為public
    int a;
    int b;
};

void operator<<(ostream &out,A &a1)//操作符過載
{
    out << "a" << a1.a << " b" << a1.b << endl;//這裡直接用out
}

void main()
{
    A a1(1, 2), a2(3, 4);
    cout<<a1;
    cout<<a2;
    system("pause");
}

總結

事實上以上程式碼均不是正規寫法,正規寫法連結將在以後給出。
最後引用王保明先生的一句話來給本文做總結:“結論倍簡單的:首先我們要承認一件事,C++中操作符的過載是用函式來實現的”。

  1. 基於王保明先生的技術推演,王老師講課真的很不錯!
  2. 結論基於王保明先生的講課內容.