在C++类的构造函数中抛出异常是一种好习惯吗?

Cyb*_*die 4 c++ constructor googletest

我有这个构造函数抛出异常

GenericSocket::GenericSocket(const string& hostname, 
                             const string& servname):
                             _hostname(hostname),
                             _servname(servname)
{  
    initHints();
    int rv;
    if((rv = getaddrinfo(_hostname.c_str(), 
                    _servname.c_str(), 
                    &_hints, 
                    &_servinfo)) != 0) {  
        throw GenericSocketException();
    }  

} 
Run Code Online (Sandbox Code Playgroud)

initHints()执行_hints的memset并设置一些变量.

我用google测试框架测试它,如下所示:

TEST(CreateObject2, getaddrinfoException)
{
    mgs_addrinfo_return = 1; 
    ASSERT_THROW(new GenericSocket("testhost", "4242"), GenericSocketException);
}
Run Code Online (Sandbox Code Playgroud)

测试因核心转储失败:

[ RUN      ] CreateObject2.getaddrinfoException
socket creation failed
terminate called after throwing an instance of 'common::GenericSocketException'
  what():  Socket creation failed
[1]    43360 abort (core dumped)  ./bin/test_common
Run Code Online (Sandbox Code Playgroud)

除了我不知道到底出了什么问题的事实,我怀疑一些未初始化的对象被删除(?),很多似乎发生在幕后,所以我开始怀疑在构造函数中抛出异常是否是好习惯.是否可以更好地将此功能放在另一个我可以在创建对象后调用的函数中,然后处理异常?

Nim*_*Nim 11

恕我直言,在构造函数中抛出异常是处理这种情况的最佳方法 - 如果没有套接字,你真的想要一个可用的对象吗?这对我没有意义.如果它没有解决该地址,那么就有理由,这是值得的例外(只要你正确处理它!)

在您的特定情况下,您应该测试返回值并使异常更有用...(例如,HostNotFound- 我猜这是这种情况)


Ale*_* C. 6

是的.你实际上别无选择:构造函数没有返回值.

但要注意异常安全.例如,请参阅http://www.drdobbs.com/184403429,或谷歌"强异常保证".实际上,构造函数抛出的对象不会被破坏(它从未存在过)并且必须处于不泄漏资源的状态.


Gen*_*yev 5

当然,当你不能构造一个对象时,唯一合理的做法是抛出异常,否则你最终会得到一些僵尸对象.并回答你的另一个问题,不,你不能破坏一个没有创建的对象.