为什么添加try块导致编译器错误

时间:2015-07-05 15:47:00

标签: c++ exception-handling

我有一些工作代码,但错误处理目前相当粗糙 - 它通常会将错误字符串发送到标准错误并退出。所以我希望它抛出异常并允许用户按照他们选择的典型处理程序来处理它。

但是,在代码中添加了一个try catch块,它给了我一个我根本不理解的编译器错误。

我的代码如下所示:

// -------------------------------------------------------------------------
sockets::TCPSocket::TCPSocket(const char* address, const int port)
{
    this->address    = address;
    this->port       = port;
    this->bufferSize = sockets::TCPSocket::DEF_BUFFER;
    sockets::TCPSocket::init();
}

// -------------------------------------------------------------------------
sockets::TCPSocket::~TCPSocket()
{
    freeaddrinfo(this->addressInfoList);
    close(this->filedes);
}

// -------------------------------------------------------------------------
void sockets::TCPSocket::init()
{
    memset(&(this->addressInfo), 0, sizeof this->addressInfo);

    addressInfo.ai_family   = AF_UNSPEC;      // Either IPv4 or IPv6
    addressInfo.ai_socktype = SOCK_STREAM;    // Uses TCP
    addressInfo.ai_flags    = AI_PASSIVE;     // Accept any IP

    // get the address info
    int status = getaddrinfo(
        this->address,
        std::to_string(this->port).c_str(),
        &(this->addressInfo),
        &(this->addressInfoList)
    );

    if (status != 0)  // any error- segfault if addressInfoList not allocated
    {
        throw GetAddrinfoException();
    }

    // create socket
    this->filedes = socket(
        this->addressInfoList->ai_family,
        this->addressInfoList->ai_socktype,
        this->addressInfoList->ai_protocol
    );

    if (this->filedes == -1)
    {
        std::cerr << "Create socket error: " << strerror(errno) << std::endl;
        exit(EXIT_FAILURE);
    }
}

// -------------------------------------------------------------------------

如您所见,我正在从构造函数中调用(私有)init()函数。我在init()函数中抛出一个GetAddrinfoException。如果我在一个try catch中将init()的调用包装在构造函数中,它可以正常工作。但是当我从我的主要调用它时 - 期望堆栈放松 - 我得到编译器错误..像这样:

int main()
    {
        using namespace std;

        // Test as client
        const char* TEST_ADDR = "www.google.com";
        try
        {
            sockets::TCPSocket socket = sockets::TCPSocket(TEST_ADDR, 80);
        }
        catch (sockets::GetAddrinfoException e) { /* do something */ }

    return 0;
}

编译器错误列出了TCPSocket的每个成员函数,并给出了以下消息:

TCPSocket/test.cpp: In function ‘int main()’:
TCPSocket/test.cpp:22:12: error: request for member ‘doConnect’ in ‘socket’, which is of non-class type ‘int(int, int, int) throw ()’
     socket.doConnect();
            ^
TCPSocket/test.cpp:23:12: error: request for member ‘doSend’ in ‘socket’, which is of non-class type ‘int(int, int, int) throw ()’
     socket.doSend("GET / HTTP/1.1\r\nHost: www.redway-soft.com\r\n\r\n");
            ^
TCPSocket/test.cpp:24:20: error: request for member ‘doRecv’ in ‘socket’, which is of non-class type ‘int(int, int, int) throw ()’
     cout << socket.doRecv() << endl;
                    ^
TCPSocket/test.cpp:34:12: error: request for member ‘restart’ in ‘socket’, which is of non-class type ‘int(int, int, int) throw ()’
     socket.restart();
            ^
TCPSocket/test.cpp:35:30: error: request for member ‘doListen’ in ‘socket’, which is of non-class type ‘int(int, int, int) throw ()’
     string received = socket.doListen();
                              ^

尽管搜索了多个教程和指南,但我找不到任何理由解决这个问题。任何帮助将不胜感激。

编辑:

类定义如下所示:

#ifndef __TCPSOCKET_HPP__
#define __TCPSOCKET_HPP__

#include <cstring>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#include <string>
#include <vector>
#include <iostream>
#include <cerrno>
#include <exception>


namespace sockets
{

    class GetAddrinfoException: std::exception
    {
        public:
            virtual const char* what() const throw()
            {
                return "getAddressinfo() failure";
            }
    };



    /**
    * @class TCPSocket, creates a HTTP/TCP Socket. TCPSocket is designed with the idea
    * that it should usually be instantiated in its own thread for most use cases.
    * @param const char* address, e.g. www.google.com
    * @param int port, which port defaults 80
    */
    class TCPSocket
    {
        private:

            /**
            * Instance vars
            */
            struct addrinfo  addressInfo;
            struct addrinfo* addressInfoList;
            int              filedes;
            const char*      address;
            int              port;
            int              bufferSize;

            /**
            * @function init, allows socket to be re-assigned a new address and port
            */
            void init();

        public:

            /**
            * pulbic class vars
            */
            static const int DEF_BUFFER   = 2000;
            static const int DEF_PORT     = 5556;
            static const int DEF_TIMEOUT  = 200000;
            static const int DEF_NUMTRIES = 5;

            /**
            * @constructor
            * @param address, to connect to default is NULL siffnifying server socket
            * @param port, port to connect/listen on
            */
            TCPSocket(const char* address = NULL, const int port = DEF_PORT);
            /**
            * @destructor
            */
            ~TCPSocket();

            /**
            * public getters
            */
            inline const char*            getAddress()         {return this->address;}
            inline const int&             getPort()            {return this->port;}
            inline const struct addrinfo& getAddressInfo()     {return this->addressInfo;}
            inline const int&             getFiledes()         {return this->filedes;}
            inline const struct addrinfo* getAddressInfoList() {return this->addressInfoList;}

            /**
            * @function setBuffer, set bufferSize to custom size
            * @param buffer, the size to set the read in buffer
            */
            inline void setBuffer(int buffer) {this->bufferSize = buffer;}

            /**
            * @function restart, cleans up and then re-initialises the socket with new params
            * @param address, to connect to
            * @param port, port to connect
            */
            void restart(const char* address = NULL, const int port = DEF_PORT);

            /**
            * @function doConnect, connect to target address
            */
            void doConnect();

            /**
            * @function doSend - sends specific message,
            * @param message e.g. "GET / HTTP/1.1\r\nHost: www.google.com\r\n\r\n"
            * would send a simple get request, or a html string could be sent back
            * in the case of send from a server socket which is responding to a
            * request.
            */
            void doSend(const char* message);

            /**
            * @function doRecv, gets return data from server
            * @param timeout, length of time to wait (micros) for data def = 100 000
            * @param numtries, number of attempts at reading data if none recv
            * @return message that has been received
            */
            std::string doRecv(int timeout = DEF_TIMEOUT, int numtries = DEF_NUMTRIES);

            /**
            * @function doListen, listens at given port and accepts a connection
            * note that this function is blocking and so any implementation should
            * probably normally be on its own thread/process, a server class should
            * be in charge of managing individual threads and sockets.
            */
            std::string doListen();


            /**
            * @function doClose, closes the filedescripter.
            */
            void doClose();
    };
}

#endif

1 个答案:

答案 0 :(得分:1)

我的水晶球告诉我你在catch块之外使用socket,但它的范围是直到try块结束。在try块中使用socket执行您需要的操作。

它没有声明socket未被声明的原因是因为它是一个函数,例如Linux的this one或Windows的this one。在try块中,局部变量会影响函数。