[英]How does C++ choose which operator overload to use?
我正在編寫一組用於自定義序列化和反序列化的類。 我認為我會使用<<和>>運算符,因為它們通常傳達這種含義。 讓我們從一個用於處理寫入通用流的類開始。
class Writer
{
public:
virtual void writeBytes(const void* p, size_t n) = 0;
template <typename T> void write(const T& v)
{
writeBytes(&v, sizeof(v));
}
template <typename T> Writer& operator<<(const T& v)
{
write(v);
return *this;
}
};
然后是一個可序列化的接口,即提供了自己的序列化方法。
class Serializable
{
public:
virtual Writer& serialize(Writer& writer) const = 0;
};
Writer& operator<<(Writer& writer, const Serializable& s)
{
s.serialize(writer);
return writer;
}
最后,我寫了一個如何使用它的示例:可序列化的緩沖區。
class SerializableBuffer : public Serializable
{
public:
SerializableBuffer() : data_(NULL), length_(0) { }
SerializableBuffer(void* data, size_t length) : data_(data), length_(length) { }
virtual Writer& serialize(Writer& writer) const
{
writer.writeBytes(data_, length_);
return writer;
}
private:
void* data_;
size_t length_;
};
所以這是有趣的部分。 顯然,如果我使用方法調用,它將完全按照預期進行。 但是使用<<操作符顯示出一些古怪之處。 我的第一個嘗試是執行以下操作:
unsigned char input[] = { 0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0x12, 0x34 };
SerializableBuffer sb(input, sizeof(input));
unsigned char d[8];
BufferWriter writer(buffer(d));
writer << sb;
這將失敗,因為輸出緩沖區不夠大。 如果我添加一個printf,結果表明它正在Writer類中調用模板! 這是古怪的部分,以下作品。
unsigned char input[] = { 0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0x12, 0x34 };
SerializableBuffer sb(buffer(input));
unsigned char d[8];
BufferWriter writer(buffer(d));
writer << (Serializable&)sb;
我猜模板引擎勝過后代嗎? 誰能解釋這是怎么回事,為什么?
它非常簡單-僅遵循重載解析規則。 您有兩個重載operator <<
,當第一個參數是Writer &
或子類時,它們可能會匹配:
template <typename T> Writer& Writer::operator<<(const T& v);
Writer& operator<<(Writer& writer, const Serializable& s);
當第二個參數是SerializableBuffer
,第一個參數可以完全匹配,而第二個參數可以與轉換匹配。 由於完全匹配會更好,因此首先匹配。
當第二個參數是Serializable
,兩者都完全匹配,因此第二個參數更好,因為它不是模板。
如果當參數是Serializable
的子類時要使模板不匹配,則可以使用enable_if
:
template <typename T>
std::enable_if<!std::is_base_of<Serializable, T>::value, Writer &>::type
operator<<(const T &v)
這將導致該模板對於Serializable
任何子類都無法實例Serializable
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.