简体   繁体   中英

invalid use of non-static member function C++ while passing member-function as a function variable

I know similar questions have been asked, but I can't point my finger on my issue. I have a class that has the following method (it is used for multi-threaded programming):

  void ServerUtil::WaitForRequst(void (*ProcessRequest)(shared_ptr<TCP> tcp), shared_ptr<struct sockaddr_in> serv_addr){


 TCPPort tcp_port(serv_addr, true);
 struct sockaddr_in client_addr; //FIXME: add these to a vector so their is a way to track clients


 int i = 0;
 while(i < m_thread_max){
     std::shared_ptr<TCP> tcp = std::make_shared<TCP>(serv_addr, &client_addr, tcp_port, true);
     std::shared_ptr<std::thread> t = std::make_shared<std::thread>(std::bind(ProcessRequest, tcp));;
     m_vector_threads.push_back(t);
     i++;
 }


 for(int j = 0; j < m_vector_threads.size();j++)
     m_vector_threads.at(j)->join();
    }

}

Now I've created a server class with the following .h file:

class Server{ public:

Server(shared_ptr<ServerUtil> serv_util, shared_ptr<struct sockaddr_in> serv_addr);
virtual void ProcessCommand(char &command) = 0;
//ProcessRequest is the primary thread(client) handler
virtual void ProcessRequest(shared_ptr<TCP> tcp) = 0;
bool SendAck(shared_ptr<TCP> tcp);
bool ReceiveAck(shared_ptr<TCP> tcp);
bool CloseConnection(shared_ptr<TCP> tcp);

protected:
shared_ptr<ServerUtil> m_serv_util;
shared_ptr<struct sockaddr_in> m_serv_addr;

};

And now the following .cpp file for the issue in question:

    Server::Server(shared_ptr<ServerUtil> serv_util, shared_ptr<struct sockaddr_in> serv_addr){

    m_serv_util = serv_util;
    m_serv_addr = serv_addr;
    m_serv_util->WaitForRequst(ProcessRequest, serv_addr);
}

And I get the following error:

 error: invalid use of non-static member function
 m_serv_util->WaitForRequst(ProcessRequest, m_serv_addr);

I also tried commenting out the constructor in the base class and doing this in a derived class (With the pure virtual functions overwritten). Any ideas?

In

void ServerUtil::WaitForRequst(void (*ProcessRequest)(shared_ptr<TCP> tcp), 
                               shared_ptr<struct sockaddr_in> serv_addr)

void (*ProcessRequest)(shared_ptr<TCP> tcp) specifies that the function will be called with a pointer to a function that matches the given void (shared_ptr<TCP> tcp) prototype.

void ProcessRequest(shared_ptr<TCP> tcp)

is a member of Server so it really looks more like

void ProcessRequest(Server * this, shared_ptr<TCP> tcp)

You can sort-of clean that up with

void ServerUtil::WaitForRequst(void (Server::*ProcessRequest)(shared_ptr<TCP> tcp), 
                               shared_ptr<struct sockaddr_in> serv_addr)

to let WaitForRequst (aside: you have a typo there than may bite you later) know that it will be getting a method of Server . But...! you will also have to pass in an object instance for this , so

void ServerUtil::WaitForRequst(void (Server::*ProcessRequest)(shared_ptr<TCP> tcp), 
                               Server * instance,
                               shared_ptr<struct sockaddr_in> serv_addr)

And this instance needs to be handed to the thread with something like

std::shared_ptr<std::thread> t = std::make_shared<std::thread>(std::bind(ProcessRequest, 
                                                                    instance, 
                                                                    tcp));

std::thread will solve the messiness involved with invoking a method pointer for you, but if you are interested, here's a big long discussion on the trials and tribulations of method pointers: Pointers to Member Functions .

Unfortunately you are doing stuff there that I think deserves another question. You do not want those shared_ptr s. No one is sharing the pointers, so std::unique_ptr or no pointer at all should be the go-to. No pointer at all looks to be good here, with the possible exception of instance (and consider a re-design if the scope of instance is unreliable or shorter than the thread).

That means

void ProcessRequest(TCP tcp)

the obligatory

void ServerUtil::WaitForRequst(void (Server::*ProcessRequest)(TCP tcp), 
                               Server * instance,
                               shared_ptr<struct sockaddr_in> serv_addr)

and

 m_vector_threads.emplace_back(ProcessRequest, 
                               instance, 
                               TCP(serv_addr, 
                                   &client_addr, 
                                   tcp_port, 
                                   true));

may be sufficient, depending on how well-written TCP is. It might be better to pass in all of the parameters and have ProcessRequest construct the TCP instance as a local variable. Forgive me if there is a minor syntax error in there. It's not like I have enough to test all this out. Feel free to kick my ass for major syntax errors, though.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM