C++運算符重載
C++中預定義的運算符的操作對象只能是基本數據類型。但實際上,對於許多用戶自定義類型(例如類),也需要類似的運算操作。這時就必須在C++中重新定義這些運算符,賦予已有運算符新的功能,使它能夠用於特定類型執行特定的操作。運算符重載的實質是函數重載,它提供了C++的可擴展性。
運算符重載是通過創建運算符函數實現的,運算符函數定義了重載的運算符將要進行的操作。運算符函數的定義與其他函數的定義類似,惟一的區別是運算符函數的函數名是由關鍵字operator和其後要重載的運算符符號構成的。運算符函數定義的一般格式如下:
<返回類型說明符> operator <運算符符號>(<參數表>)
{
<函數體>
}
(1) 除了類屬關系運算符"."、成員指針運算符".*"、作用域運算符"::"、sizeof運算符和三目運算符"?:"以外,C++中的所有運算符都可以重載。
(2) 重載運算符限制在C++語言中已有的運算符范圍內的允許重載的運算符之中,不能創建新的運算符。
(3) 運算符重載實質上是函數重載,因此編譯程序對運算符重載的選擇,遵循函數重載的選擇原則。
(4) 用戶自定義類的運算符一般都必須重載後方可使用,但兩個例外,運算符“=”和“&”不必用戶重載.
哪些運算符可以用作重載?幾乎所有的運算符都可用作重載。具體包含:
算術運算符:=,-,*,/,%,++,--
位操作運算符:—,|,~,^,<<,>>;
邏輯運算符:!&&,||;
比較運算符:>,<,>=,<=,==,!=
賦值運算符:=,+=,- = ,*=,%=,\=^=,<<=,>>=;
其他運算符:[ ],()->, ',new,delete,new[],delete[],->* .
運算符有兩種重載形式:成員函數形式和友元函數形式。這兩種形式都可訪問類中的私有成員。
實例:自定義一個int包裹類,包裝int,並且支持+運算符和=運算符
1.用成員函數來重載運算符
class Integer {
public:
Integer();
Integer(int value);
Integer operator+(int value);
void operator=(int value);
private:
int m_value;
};
//integer.cpp
#include "integer.h"
Integer::Integer() {
m_value = 0;
}
Integer::Integer(int value) {
m_value = value;
}
Integer Integer::operator+(int value) {
int tmpValue = m_value + value;
return Integer(tmpValue);
}
void Integer::operator=(int value) {
m_value = value;
}
使用示例:
Integer integer = Integer(10);
Integer tmpInteger = 100; //重載=運算符
tmpInteger = integer + 1; //重載+運算符
2.使用友元函數來重載運算符
使用成員函數重載運算符,我們做到了實現 integer + 1,可是如果是 1 + integer呢,這個時候我們必須使用友元函數重載+運算符:
//integer.h
class Integer {
public:
Integer();
Integer(int value);
Integer operator+(int value);
void operator=(int value);
operator int() const;
private:
int m_value;
friend Integer operator+(int value, Integer integer);
};
//Integer operator +(Integer integer, int value); //不能聲明該函數,否則會和成員函數沖突
Integer operator+(int value, Integer integer);
//integer.cpp
#include "integer.h"
Integer::Integer() {
m_value = 0;
}
Integer::Integer(int value) {
m_value = value;
}
Integer Integer::operator+(int value) {
int tmpValue = m_value + value;
return Integer(tmpValue);
}
void Integer::operator=(int value) {
m_value = value;
}
Integer::operator int() const {
return m_value;
}
Integer operator+(int value, Integer integer) {
int tmpValue = integer.m_value + value;
return Integer(tmpValue);
}
使用示例:
Integer integer = Integer(10);
Integer tmpInteger = 100; //重載=運算符
tmpInteger = integer + 1; //重載Integer成員函數+運算符
tmpInteger = 1 + tmpInteger;//重載友元函數+運算符
轉換運算符重載:
從上述代碼我們看到Integer integer = 1;(隱式調用構造函數),確實很方便,但是如果要實現 int i = Integer(100),實現自定義類型到內部類型的轉換或者已有的類型,就需要轉換運算符了。
轉換運算符的的形式如下:
X::operator T()
其中T是類型。
代碼示例如下:
//integer.h
class Integer {
public:
Integer();
Integer(int value);
Integer operator+(int value);
void operator=(int value);
operator int() const; //int 轉換運算符
private:
int m_value;
friend Integer operator+(int value, Integer integer);
};
//Integer operator +(Integer integer, int value); //不能聲明該函數,否則會和成員函數沖突
Integer operator+(int value, Integer integer);
//integer.cpp
#include "integer.h"
#include <stdio.h>
#include <stdlib.h>
Integer::Integer() {
m_value = 0;
}
Integer::Integer(int value) {
m_value = value;
}
Integer Integer::operator+(int value) {
int tmpValue = m_value + value;
return Integer(tmpValue);
}
void Integer::operator=(int value) {
m_value = value;
}
Integer::operator int() const {
return m_value;
}
Integer operator+(int value, Integer integer) {
int tmpValue = integer.m_value + value;
return Integer(tmpValue);
}
使用示例:
Integer integer = Integer(10);
Integer tmpInteger = 100; //重載=運算符
tmpInteger = integer + 1; //重載Integer成員函數+運算符
tmpInteger = 1 + tmpInteger;//重載友元函數+運算符
int num = tmpInteger; //重載int 轉換運算符
重載++運算符:
前綴各後綴運算兩種,為了區分這兩種運算,將後綴運算符視為雙目運算符,示例代碼如下:
//integer.h
class Integer {
public:
Integer();
Integer(int value);
Integer operator+(int value);
void operator=(int value);
operator int() const; //int 轉換運算符
Integer operator++(); //重載 ++Integer
Integer operator++(int value);//重載 Integer++
private:
int m_value;
friend Integer operator+(int value, Integer integer);
};
//Integer operator +(Integer integer, int value); //不能聲明該函數,否則會和成員函數沖突
Integer operator+(int value, Integer integer);
//integer.cpp
#include "integer.h"
Integer::Integer() {
m_value = 0;
}
Integer::Integer(int value) {
m_value = value;
}
Integer Integer::operator+(int value) {
int tmpValue = m_value + value;
return Integer(tmpValue);
}
void Integer::operator=(int value) {
m_value = value;
}
Integer::operator int() const {
return m_value;
}
Integer Integer::operator++() {
Integer tmpInteger;
tmpInteger = ++m_value;
return tmpInteger;
}
Integer Integer::operator++(int value) {
Integer tmpInteger;
tmpInteger = m_value++;
return tmpInteger;
}
Integer operator+(int value, Integer integer) {
int tmpValue = integer.m_value + value;
return Integer(tmpValue);
}
使用示例:
Integer integer = Integer(10);
Integer tmpInteger = 100; //重載=運算符
tmpInteger = integer + 1; //重載Integer成員函數+運算符
tmpInteger = 1 + tmpInteger;//重載友元函數+運算符
int num = tmpInteger; //重載int 轉換運算符
tmpInteger = integer++; //重載 Integer++
tmpInteger = ++integer; //重載 ++Integer
兩種重載形式的比較:
在多數情況下,將運算符重載為類的成員函數和類的友元函數都是可以的。但成員函數運算符與友元函數運算符也具有各自的一些特點:
(1) 一般情況下,單目運算符最好重載為類的成員函數;雙目運算符則最好重載為類的友元函數。
(2) 以下一些雙目運算符不能重載為類的友元函數:=、()、[]、->。
(3) 類型轉換函數只能定義為一個類的成員函數而不能定義為類的友元函數。
(4) 若一個運算符的操作需要修改對象的狀態,選擇重載為成員函數較好。
(5) 若運算符所需的操作數(尤其是第一個操作數)希望有隱式類型轉換,則只能選用友元函數。
(6) 當運算符函數是一個成員函數時,最左邊的操作數(或者只有最左邊的操作數)必須是運算符類的一個類對象(或者是對該類對象的引用)。如果左邊的操作數必須是一個不同類的對象,或者是一個內部類型的對象,該運算符函數必須作為一個友元函數來實現。
(7) 當需要重載運算符具有可交換性時,選擇重載為友元函數。