我通常不明确地调用析构函数。但是我正在设计TCP服务器类,它看起来像这样:
class Server {
public:
Server() {
try {
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData))
throw std::runtime_error("WSAStartup function failed.");
...
if ((m_scListener = socket(pAddr->ai_family, pAddr->ai_socktype, pAddr->ai_protocol)) == INVALID_SOCKET)
throw std::runtime_error("'socket' function failed.");
...
}
catch (std::exception& ex) {
this->~Server();
throw;
}
}
~Server() {
if (m_scListener != INVALID_SOCKET) {
closesocket(m_scListener);
m_scListener = INVALID_SOCKET;
}
WSACleanup();
}
private:
SOCKET m_scListener = INVALID_SOCKET;
}
上面的代码是否被视为不良做法或设计?建议的设计方式是什么?我这样写是因为构造函数不能返回NULL。我应该将构造函数设为私有,并编写创建Server类实例的静态方法吗?
=====更新=====
好,总结一下答案,我得出以下结论:
明确地调用析构函数通常不是一个好主意,即使它按预期工作也是如此,这是不寻常的,并且其他将要处理您的代码的C ++程序员可能会对此方法感到困惑。因此,最好避免显式调用析构函数。
将我原来的RAII类分解为微型RAII类似乎是一个不错的解决方案。但是,恐怕我的真实代码中有太多需要进行清理的API调用(closesocket,CloseHandle,DeleteCriticalSection等)。其中一些仅被调用一次,并且永远不会被重用,将它们全部移到单独的RAII类中对我来说似乎太疯狂了。这也会增加我的代码。
我认为最有帮助的答案是来自MM:
更好的解决方案是将初始化代码保留在构造函数中,并在丢弃之前调用cleanup函数。
遵循MM的建议,我以这种方式重写了代码:
class Server {
public:
Server() {
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData))
ThrowError("WSAStartup function failed.", true);
...
if ((m_scListener = socket(pAddr->ai_family, pAddr->ai_socktype, pAddr->ai_protocol)) == INVALID_SOCKET)
ThrowError("'socket' function failed.", true);
...
}
~Server() { CleanUp(); }
private:
SOCKET m_scListener = INVALID_SOCKET;
void ThrowError(const char* error, bool cleanUp) {
if (cleanUp)
CleanUp();
throw std::runtime_error(error);
}
void CleanUp() {
if (m_scListener != INVALID_SOCKET) {
closesocket(m_scListener);
m_scListener = INVALID_SOCKET;
}
WSACleanup();
}
};
我相信这种设计遵循RAII模式,但是只有一个类而不是3-4个微型RAII类。
建议的设计方式是什么?
我会说:更多的RAII。就像是:
class WSARaii
{
public:
WSARaii()
{
if (WSAStartup(MAKEWORD(2, 2), &wsaData))
throw std::runtime_error("WSAStartup function failed.");
}
~WSARaii()
{
WSACleanup();
}
WSARaii(const WSARaii&) = delete;
WSARaii& operator =(const WSARaii&) = delete;
private:
WSADATA wsaData;
};
class Socket
{
public:
Socket(..) : m_scListener(socket(pAddr->ai_family, pAddr->ai_socktype, pAddr->ai_protocol) {
if (m_scListener == INVALID_SOCKET)
throw std::runtime_error("'socket' function failed.");
}
~Server() {
if (m_scListener != INVALID_SOCKET) {
closesocket(m_scListener);
}
}
private:
SOCKET m_scListener
};
最后
class Server {
public:
Server() : wsa(), socket(..) {}
private:
WSARaii wsa;
Socket socket;
};
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句