C++運算符重載需要注意的地方

有時候自己寫一個類,需要重載運算符,但對於一些操作符(如==<>等),可以在類裏寫,也可以在類外寫。那麼 C++ 編譯器會去怎麼調用呢?


首先,我們知道,“重載” 機制可以允許多個函數有相同的函數名,但參數列表必須不同。C++編譯器經過名字改編(name mangling),可以在調用時依據所傳實參找到“最符合”的函數實體進行調用。而運算符重載亦是如此。


首先,我們有一個類:

class CMyCls
{
public:
	bool operator == (const CMyCls& rhs);				// 1.
	
	bool operator == (const CMyCls& rhs) const;			// 2.

	bool operator == (CMyCls& rhs);						// 3.

	bool operator == (CMyCls& rhs) const;				// 4.
};


void f1 (CMyCls& lhs, const CMyCls& rhs);
{
	lhs == rhs;
}

void f2 (const CMyCls& lhs, const CMyCls& rhs);
{
	lhs == rhs;
}

void f3 (CMyCls& lhs, CMyCls& rhs);
{
	lhs == rhs;
}

void f4 (const CMyCls& lhs, CMyCls& rhs)
{
	lhs == rhs;
}

那麼 f1 - f4 這四個函數將會如何調用呢?其實,f1函數會調到CMyCls類中1 處註釋所標的函數,f2會調到 2 處註釋所標的函數,f3f4依次類推。


那麼,如果我在類裏面有一個運算符重載,在類外也有,會調用哪一個呢?比如:

class CMyCls
{
public:
	bool operator == (const CMyCls& rhs) const
	{
		// ...
	}
};


bool operator == (const CMyCls& lhs, const CMyCls& rhs)
{
	// ...
}


void f(const CMyCls& lhs, const CMyCls& rhs)
{
	lhs == rhs;
}

但很不幸的是,這樣編不過。因爲對於 f 函數的調用來說,編譯器不知道調哪一個會比較好,因爲同時存在兩份“最適合”的重載函數,所以產生歧義。但這樣是可以編過的,思考下爲什麼:

class CMyCls
{
public:
	bool operator == (const CMyCls& rhs)
	{
		// ...
	}
};


bool operator == (const CMyCls& lhs, const CMyCls& rhs)
{
	// ...
}


void f1(const CMyCls& lhs, const CMyCls& rhs)
{
	lhs == rhs;
}


void f2(CMyCls& lhs, const CMyCls& rhs)
{
	lhs == rhs;
}

上面 f1會調到全局的函數operator ==,而f2會調到 CMyCls的成員函數operator ==。所以,最好的寫法是只在類裏或類外重載兩個參數均爲const的版本。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章