class 对象充当流的 C++ 重载 << 运算符
C++ overload << operator for class object acting as stream
所以我浏览了很多其他线程,但是 none 与我对这个确切主题的问题有关。我正在编写一个 C++ 库来进行套接字通信。我有一个 TCP 套接字 class,它处理 TCP 套接字上的所有操作(设置、read/write 等)。我希望能够使用 << 和 >> 运算符读取和写入数据 to/from 一个 TCP 套接字对象。例如,我希望能够以这种方式将 double 写入套接字:
double x;
TcpSocket *sock = new TcpSocket();
//socket setup stuff here...
sock << x;
目前,我在 TcpSocket 中有两个模板化的重载运算符函数 class:
template<typename T>
TcpSocket operator<<(TcpSocket sock, T &val)
{
unsigned char bytesOfVal[] = //parse bytes of val here...
sock.Write(bytesOfVal, sizeof(bytesOfVal));
}
-
template<typename T>
TcpSocket operator>>(TcpSocket sock, T &val)
{
std::stringstream ss;
byte buf[sizeof(val)];
sock.Read(buf, sizeof(buf));
ss.str(std::string(buf));
ss >> val;
}
其中 sock.Read( ) 和 sock.Write( ) 使用套接字文件描述符发出系统调用 read( ) 和 write( )(不是很相关,仅供参考)。这些函数被模板化,试图在一个地方获取几乎所有数据类型的字节。
所以我的问题是:
- 这些重载的运算符函数会按照我希望的方式工作吗?
如果可行,我可以将它们链接在一起吗,例如:
袜子 << 45.8 << 33.9 << "numbers";
============================================= ============================
这是我更新的运算符函数:
//Write to socket
template<typename T>
TcpSocket& operator<<(TcpSocket& sock, T &val)
{
size_t buflen = sizeof(val);
unsigned char buf[buflen];
memcpy(buf, &val, buflen);
sock.Write(buf, buflen);
return sock;
}
和
//Read from socket
template<typename T>
TcpSocket& operator>>(TcpSocket &sock, T &val)
{
size_t buflen = sizeof(val);
unsigned char buf[buflen];
int numBytesRead = 0;
numBytesRead = sock.Read(buf, buflen);
memcpy(&val, buf, numBytesRead);
return sock;
}
为了使您的函数正常工作,您需要使用对 TcpSocket
的引用作为输入参数以及 return 类型。另外 val
需要是 T const&
,而不是 T&
。
template<typename T>
TcpSocket& operator<<(TcpSocket& sock, T const&val)
{
unsigned char bytesOfVal[] = //parse bytes of val here...
sock.Write(bytesOfVal, sizeof(bytesOfVal));
return sock;
}
现在,您可以使用:
sock << 45.8 << 33.9 << "numbers";
如果您也希望能够使用:
sock << 45.8 << 33.9 << "numbers" << std::endl;
你需要另一个功能。
TcpSocket& operator<<(TcpSocket& soc,
std::ostream&(*f)(std::ostream&))
{
std::ostringstream s;
s << f;
return sock << s.str();
}
您提出的代码
template<typename T>
TcpSocket operator<<(TcpSocket sock, T &val)
{
unsigned char bytesOfVal[] = //parse bytes of val here...
sock.Write(bytesOfVal, sizeof(bytesOfVal));
}
还有另一个主要缺陷(除了 Sahu 指出的缺陷):它将以二进制形式写入您的数据,并且无法正常工作 std::ostream。
例如
TcpSocket socket ;
socket << std::string("Hello") ;
不会写 'Hello' 但有些数据不太好理解(大小?指向实际文本的指针?取决于实现)。
我建议你写你自己的stream buf。这样你就可以使用所有现有的 std::ostream 东西。
std::ostream ost ;
ost.imbue(new my_sockect_streambuf) ;
// 或 std::ostream ost(new my_socket_strembuf) ;
ost << 1.2 << "text" << std::endl ;
您可以在此处找到参考资料:How do I create my own ostream/streambuf? (I consider your question nearly a duplicate of this one) or here: http://www.mr-edd.co.uk/blog/beginners_guide_streambuf。
可能太多了,但我认为这是要走的路。
所以我浏览了很多其他线程,但是 none 与我对这个确切主题的问题有关。我正在编写一个 C++ 库来进行套接字通信。我有一个 TCP 套接字 class,它处理 TCP 套接字上的所有操作(设置、read/write 等)。我希望能够使用 << 和 >> 运算符读取和写入数据 to/from 一个 TCP 套接字对象。例如,我希望能够以这种方式将 double 写入套接字:
double x;
TcpSocket *sock = new TcpSocket();
//socket setup stuff here...
sock << x;
目前,我在 TcpSocket 中有两个模板化的重载运算符函数 class:
template<typename T>
TcpSocket operator<<(TcpSocket sock, T &val)
{
unsigned char bytesOfVal[] = //parse bytes of val here...
sock.Write(bytesOfVal, sizeof(bytesOfVal));
}
-
template<typename T>
TcpSocket operator>>(TcpSocket sock, T &val)
{
std::stringstream ss;
byte buf[sizeof(val)];
sock.Read(buf, sizeof(buf));
ss.str(std::string(buf));
ss >> val;
}
其中 sock.Read( ) 和 sock.Write( ) 使用套接字文件描述符发出系统调用 read( ) 和 write( )(不是很相关,仅供参考)。这些函数被模板化,试图在一个地方获取几乎所有数据类型的字节。
所以我的问题是:
- 这些重载的运算符函数会按照我希望的方式工作吗?
如果可行,我可以将它们链接在一起吗,例如:
袜子 << 45.8 << 33.9 << "numbers";
============================================= ============================ 这是我更新的运算符函数:
//Write to socket
template<typename T>
TcpSocket& operator<<(TcpSocket& sock, T &val)
{
size_t buflen = sizeof(val);
unsigned char buf[buflen];
memcpy(buf, &val, buflen);
sock.Write(buf, buflen);
return sock;
}
和
//Read from socket
template<typename T>
TcpSocket& operator>>(TcpSocket &sock, T &val)
{
size_t buflen = sizeof(val);
unsigned char buf[buflen];
int numBytesRead = 0;
numBytesRead = sock.Read(buf, buflen);
memcpy(&val, buf, numBytesRead);
return sock;
}
为了使您的函数正常工作,您需要使用对 TcpSocket
的引用作为输入参数以及 return 类型。另外 val
需要是 T const&
,而不是 T&
。
template<typename T>
TcpSocket& operator<<(TcpSocket& sock, T const&val)
{
unsigned char bytesOfVal[] = //parse bytes of val here...
sock.Write(bytesOfVal, sizeof(bytesOfVal));
return sock;
}
现在,您可以使用:
sock << 45.8 << 33.9 << "numbers";
如果您也希望能够使用:
sock << 45.8 << 33.9 << "numbers" << std::endl;
你需要另一个功能。
TcpSocket& operator<<(TcpSocket& soc,
std::ostream&(*f)(std::ostream&))
{
std::ostringstream s;
s << f;
return sock << s.str();
}
您提出的代码
template<typename T>
TcpSocket operator<<(TcpSocket sock, T &val)
{
unsigned char bytesOfVal[] = //parse bytes of val here...
sock.Write(bytesOfVal, sizeof(bytesOfVal));
}
还有另一个主要缺陷(除了 Sahu 指出的缺陷):它将以二进制形式写入您的数据,并且无法正常工作 std::ostream。
例如
TcpSocket socket ;
socket << std::string("Hello") ;
不会写 'Hello' 但有些数据不太好理解(大小?指向实际文本的指针?取决于实现)。
我建议你写你自己的stream buf。这样你就可以使用所有现有的 std::ostream 东西。
std::ostream ost ;
ost.imbue(new my_sockect_streambuf) ;
// 或 std::ostream ost(new my_socket_strembuf) ; ost << 1.2 << "text" << std::endl ;
您可以在此处找到参考资料:How do I create my own ostream/streambuf? (I consider your question nearly a duplicate of this one) or here: http://www.mr-edd.co.uk/blog/beginners_guide_streambuf。
可能太多了,但我认为这是要走的路。