有時候自己寫一個類,需要重載運算符,但對於一些操作符(如==、<、>等),可以在類裡寫,也可以在類外寫。那麼 C++ 編譯器會去怎麼調用呢?
首先,我們知道,“重載” 機制可以允許多個函數有相同的函數名,但參數列表必須不同。C++編譯器經過名字改編(name mangling),可以在調用時依據所傳實參找到“最符合”的函數實體進行調用。而運算符重載亦是如此。
首先,我們有一個類:
[cpp]
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 處注釋所標的函數,f3、f4依次類推。
那麼,如果我在類裡面有一個運算符重載,在類外也有,會調用哪一個呢?比如:
[cpp]
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 函數的調用來說,編譯器不知道調哪一個會比較好,因為同時存在兩份“最適合”的重載函數,所以產生歧義。但這樣是可以編過的,思考下為什麼:
[cpp]
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;
} www.2cto.com
void f2(CMyCls& lhs, const CMyCls& rhs)
{
lhs == rhs;
}
上面 f1會調到全局的函數operator ==,而f2會調到 CMyCls的成員函數operator ==。所以,最好的寫法是只在類裡或類外重載兩個參數均為const的版本。