2017-11-24 6 views
0

C++ Anfänger hier.Wie Netzwerkfunktionen von anderen Klassen am besten zugänglich gemacht werden?

Ich versuche, C++ beizubringen, indem ich an einem Projekt arbeite, um einen Roboter zu erstellen, der Befehle von einem Remote-Server erhält und Telemetrie zurück an einen Remote-Server sendet.

Ich habe eine TcpCom Klasse auf dem Roboter, die die Socket-Verbindung und öffentliche Funktionen enthalten Nachrichten zu senden und Empfangen von Nachrichten vom Server:

#ifndef TCPCOM_H 
#define TCPCOM_H 
#define BOOST_DATE_TIME_NO_LIB 
#include <boost/asio.hpp> 
#include <boost/interprocess/sync/interprocess_semaphore.hpp> 
#include <deque> 
#include <mutex> 
#include "COM.h" 

class TcpCom : public COM 
{ 

    public: 
     TcpCom() : io_srv(), tcpSocket(io_srv), remoteHost(""), remotePort(""), connectedToRemoteHost(false), outboundMsgQueue(), outboundMsgQueueMutex(), 
     messagesInOutboundMsgQueue(0), incomingMsgQueue(), incomingMsgQueueMutex() 
     {} 
     int initialize(); 
     void connectToRemoteHost(const std::string host, const std::string port); 
     void disconnectFromRemoteHost(); 
     bool messagesWaitingInIncomingMsgQueue(); 
     SoftwareBusMsg getMsgFromIncomingMsgQueue(); 
     void addMsgToOutboundMsgQueue(SoftwareBusMsg& sbMsg); 
     bool isConnected(); 

    private: 
     void writeOutboundMsgToSocket(); 
     void deserializeHeader(std::string headerStr, MsgHeader& msgHdr); 
     void addMessageToIncomingMsgQueue(SoftwareBusMsg& sbMsg); 
     void readIncomingMsgHeader(MsgHeader& msgHdr); 
     std::string readIncomingMsgData(uint32_t msgDataLength); 
     SoftwareBusMsg readMsgFromSocket(); 
     void incomingMsgThread(); 
     void outboundMsgThread(); 
     void startReadAndWriteThreads(); 

     boost::asio::io_service io_srv; 
     boost::asio::ip::tcp::socket tcpSocket; 
     std::string remoteHost; 
     std::string remotePort; 
     bool connectedToRemoteHost; 

     std::deque<std::string> outboundMsgQueue; 
     std::mutex outboundMsgQueueMutex; 
     boost::interprocess::interprocess_semaphore messagesInOutboundMsgQueue; 

     std::deque<SoftwareBusMsg> incomingMsgQueue; 
     std::mutex incomingMsgQueueMutex; 
     //boost::interprocess::interprocess_semaphore messagesInIncomingMsgQueue; 

}; 
#endif 

ich die anderen Klassen will, wie die Verantwortlichen für die Motorsteuerung , um Nachrichten für Telemetrie-/Fehlerberichte an den Server senden zu können. Ich mag mich hier irren, aber es scheint, als wäre es ein schlechtes Design, eine Instanz der Klasse TcpCom direkt an jede Klasse zu übergeben, die die Fähigkeit benötigt, Nachrichten an den Server zu senden.

Stattdessen habe ich versucht, eine EventReporter Klasse zu erstellen, die über ein privates Mitglied verfügt, das eine Referenz auf der Klasse TcpCom ist. Dies würde die Kapselung von Code für die Behandlung verschiedener Arten von Ereignissen (Informationen, Fehler) ermöglichen, und ich könnte ein initialisiertes "EventReporter" -Objekt an alles übergeben, was es benötigt.

#include "TcpCom.hpp" 

class EventReporter 
{ 
    public: 
     EventReporter(TcpCom& tcpComIn) : tcpCom(tcpComIn) 
     {} 
     //Will contain call to tcpCom.addMsgToOutboundMsgQueue() 
     void reportEvent(std::string eventType, std::string message); 
    private: 
     TcpCom tcpCom; 
}; 

Als ich versuchte, diesen Code kompilieren habe ich ein paar Fehler:

error: use of deleted function 'TcpCom::TcpCom(const TcpCom&)' 

error: use of deleted function 'boost::asio::io_service(const boost::asio::io_service&)' 

Es sieht aus wie meine neue Klasse eine Kopie TcpCom machen würde versuchen, was ich dachte, dass ich zu vermeiden, indem man es als Referenz.

Sollte ich etwas wie unique_ptr verwenden, um das Kopieren von TcpCom zu vermeiden, oder gibt es eine bessere Möglichkeit, Netzwerkfunktionen von anderen Klassen aus zugänglich zu machen?

Danke!

Antwort

1

Art von warf auf, ob dies zu beantworten oder als Tippfehler zu schließen, so werde ich posten und lassen Sie die Frage Fragesteller mir sagen.

In

class EventReporter 
{ 
    public: 
     EventReporter(TcpCom& tcpComIn) : tcpCom(tcpComIn) 
     {} 
     //Will contain call to tcpCom.addMsgToOutboundMsgQueue() 
     void reportEvent(std::string eventType, std::string message); 
    private: 
     TcpCom tcpCom; //<- this is not a reference 
}; 

TcpCom tcpCom; eine Instanz von TcpCom definiert, kein Verweis auf eine TcpCom als Asker erklärte sie wollten, so tcpCom(tcpComIn) in der Elementinitialisierung Liste (Good ihnen die Liste für die Verwendung durch die Viele C++ - Programmierer, die denken, dass sie nicht mehr lernen, scheinen nicht zu wissen, dass sie existieren) führt die Kopie durch, die sie zu vermeiden versuchen, indem sie durch Referenz in der Parameterliste gehen.

Die Fehlermeldung resultiert aus Mitgliedern (mindestens std :: mutex. Mehrere Kopien eines Mutex wären schlecht) von TcpCom nicht kopierbar, so dass Sie nicht kopieren können, auch wenn Sie möchten.

Die einfache Lösung ist

class EventReporter 
{ 
    public: 
     EventReporter(TcpCom& tcpComIn) : tcpCom(tcpComIn) 
     {} 
     //Will contain call to tcpCom.addMsgToOutboundMsgQueue() 
     void reportEvent(std::string eventType, std::string message); 
    private: 
     TcpCom & tcpCom; //<- change made here 
}; 

Sofern der Asker andere nicht kopierbare Objekte hat auch sonst in ihrem Code, in dem oder der die Instanz EventReporter kopiert die Quelle überleben können TcpCom sie sollten gut zu gehen.

+0

Ich würde nicht sagen, es war ein Tippfehler - ich dachte fälschlicherweise, dass, wenn ich in einer Referenz (TcpCom & tcpComIn) übergeben, dass das Mitglied (TcpCom tcpCom) auch eine Referenz wäre. TcpCom sollte EventReporter definitiv überleben, also sollte diese Lösung gut sein :) – user3878723

Verwandte Themen