关于在类中重载左移运算符

首先吐槽一下,百度和谷歌上面搜索到的都是怎么通过左移运算符输出数据到ostream中去,找了半天都没有关于怎么使用移位运算符输入数据到对象中去,也可能是关键字不对


假设有类http_get_options:


使用以下代码,存数据到对象中去,得到类似字符串:key1=value1&key2=value2&key3=value3........

int main(int argc, char **argv)
{
	http_get_options httpget;

	httpget << "key1" << "value1" << "key2" << "value2" << "key3" << "value3" << "key4" << "value4";

	httpget.show();

	return 0;
}


很明显,使用运算符重载就能实现

首先实现,只传入const char *类型的字符串重载函数

需要说明的是:返回对象引用,是为了能够多次使用<<,即对象 << 数据1 << 数据2.........

如果定义为void operator <<(const char *s),那么只能这样用:

httpget << "key1";
httpget << "value1";
httpget << "key2";
httpget << "value2";

回想一下std::stringstream的用法,这样用是不是特别别扭

至于为什么:因为<<运算符是双目运算符,而且运算方向是从左到右结合的

首先遇到第一个<<,httpget << "key1",如果返回type:void,那么遇到第二个<<,(type:void) << "value1",很明显是不能编译通过的

error: invalid operands of types ‘void’ and ‘const char [7]’ to binary ‘operator<<’

因此,定义为http_get_options &operator <<(const char *s)

首先遇到第一个<<,httpget << "key1",返回type:http_get_options &,那么遇到第二个<<,(type:http_get_options &) << "value1",如此循环直到最后一个<<

以下是完整源码:

http_get_options &operator <<(const char *s)
{
	// 判断是否是第一次存入数据
	if(0 < m_data.str().size())
	{
		// 判断最后一位是否为'='
		// 如果不是,那么存入的是{keyname}=,再此之前要存入分隔符'&'
		// 如果是,那么当前存入的是{value}
		if('=' != *m_data.str().rbegin())
		{
			m_data << '&';
			m_data << s;
			m_data << '=';
		}
		else
		{
			m_data << s;
		}
	}
	else
	{
		// 第一次存入数据,写入{keyname}=
		m_data << s;
		m_data << '=';
	}

	return *this;
}

以上代码使用上没有问题,但是传入的参数不只有const char *,还有int double等等其他类型

为了方便起见,将上述函数改为类成员模板函数即可(不用每个参数类型都重载一次,模板的优点)

template
http_get_options &operator <<(const T &t)
{
	// 判断是否是第一次存入数据
	if(0 < m_data.str().size())
	{
		// 判断最后一位是否为'=',通过迭代器,得到最后一个字符,rbegin() = end() - 1
		// 如果不是,那么存入的是{keyname}=,再此之前要存入分隔符'&'
		// 如果是,那么当前存入的是{value}
		if('=' != *m_data.str().rbegin())
		{
			m_data << '&';
			m_data << t;
			m_data << '=';
		}
		else
		{
			m_data << t;
		}
	}
	else
	{
		// 第一次存入数据,写入{keyname}=
		m_data << t;
		m_data << '=';
	}

	return *this;
};




整体代码如下:

#include 
#include 

class http_get_options {
public:
	http_get_options() {};
	~http_get_options() {};
#if 1
	template
	http_get_options &operator <<(const T &t)
	{
		// 判断是否是第一次存入数据
		if(0 < m_data.str().size())
		{
			// 判断最后一位是否为'='
			// 如果不是,那么存入的是{keyname}=,再此之前要存入分隔符'&'
			// 如果是,那么当前存入的是{value}
			if('=' != *m_data.str().rbegin())
			{
				m_data << '&';
				m_data << t;
				m_data << '=';
			}
			else
			{
				m_data << t;
			}
		}
		else
		{
			// 第一次存入数据,写入{keyname}=
			m_data << t;
			m_data << '=';
		}

		return *this;
	};
#else
	http_get_options &operator <<(const char *s)
	{
		// 判断是否是第一次存入数据
		if(0 < m_data.str().size())
		{
			// 判断最后一位是否为'='
			// 如果不是,那么存入的是{keyname}=,再此之前要存入分隔符'&'
			// 如果是,那么当前存入的是{value}
			if('=' != *m_data.str().rbegin())
			{
				m_data << '&';
				m_data << s;
				m_data << '=';
			}
			else
			{
				m_data << s;
			}
		}
		else
		{
			// 第一次存入数据,写入{keyname}=
			m_data << s;
			m_data << '=';
		}

		return *this;
	}
#endif

	void show(void)
	{
		std::cout << m_data.str() << std::endl;
	};

private:
	std::stringstream m_data;
};

int main(int argc, char **argv)
{
	http_get_options httpget;

	httpget << "key1" << "value1" << "key2" << "value2" << "key3" << "value3" << "key4" << "value4";

	httpget.show();

	return 0;
}


你可能感兴趣的:(C/C++)