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

why is adding try block causing compiler error

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

但是,在代码中添加了一个 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。如果我将对 init() 的调用包装在构造函数中的 try catch 中,它就可以正常工作。但是当我从我的 main 调用它时 - 期望堆栈展开 - 我得到一个编译器错误..像这样:

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();
                              ^

尽管搜索了多个教程和指南,但我找不到导致此问题的任何原因。任何帮助将不胜感激。

编辑:

class 定义如下所示:

#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

我的 crystal 球告诉我您正在使用 socket 超出 catch 块,但它的范围是直到 try 块结束。在 try 块中使用 socket 执行您需要的操作。

之所以没有说socket没有声明是因为它是一个函数,比如this one for Linux or this one for Windows。在你的 try 块中,局部变量隐藏了函数。