gpt4 book ai didi

c++ - C++ 如何选择要使用的运算符重载?

转载 作者:行者123 更新时间:2023-11-28 02:19:12 25 4
gpt4 key购买 nike

我正在编写一组用于自定义序列化和反序列化的类。我想我会使用 << 和 >> 运算符,因为它们通常传达了这个意思。让我们从一个用于处理写入通用流的类开始。

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;
}
};

然后有一个可序列化的接口(interface),即提供它自己的序列化方法。

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 的任何子类实例化。 .

关于c++ - C++ 如何选择要使用的运算符重载?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33106610/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com