2016-04-20 4 views
1

Ich versuche eine Bibliothek zu erstellen, die mit einem Arduino mehrere Weboperationen ausführen kann, unabhängig davon, ob der Arduino einen EthernetClient oder einen WiFiClient verwendet. Es ist viele, viele Jahre her, seit ich irgendetwas in C++ berührte, und ich denke, ich vermassle diesen ganzen "Zeiger" gegen "Referenz" gegen "Wert" Zeug.C++: Korrekte Methode zum Übergeben einer abgeleiteten Klasse an eine abstrakte Klasse

Ich kann nicht scheinen, wann es eine & oder ein *, oder was auch immer zu verwenden, damit ich eine generische Client-Datenklasse verwenden kann, die entweder auf den WiFiClient oder den EthernetClient-Wert festgelegt wird .

Kann jemand bitte helfen zu erklären, was ich falsch mache, warum es nicht funktioniert, und möglicherweise, was der richtige Weg ist, dies zu tun, damit es funktioniert?

Hier ist, was ich in meinem Kopf habe:

#ifndef web_h 
#define web_h 

#include "Arduino.h" 
#include "Client.h" 
#include "WiFiClient.h" 
#include "EthernetClient.h" 

class web { 
    public: 
    web(WiFiClient* client); 
    web(EthernetClient* client); 
    void makeCall(); 
    private: 
    Client& _client; 
    String getRequest(String server, int port, String url); 
}; 
#endif 

Hier ist, was ich in meiner Bibliothek cpp bekam:

#include "Arduino.h" 
#include "web.h" 
#include "Client.h" 
#include "WiFiClient.h" 
#include "EthernetClient.h" 

    web::web(WiFiClient* client){ 
    _client = client; 
    } 
    web::web(EthernetClient* client){ 
    _client = client; 
    } 
    void web::makeCall(){ 
    String response = getRequest("www.google.com", 80, "/"); 
    Serial.println(response); 
    } 

    String web::getRequest(String server, int port, String url){ 
     String response = ""; 
     char cServer[server.length() + 1]; 
     server.toCharArray(cServer, server.length() + 1); 

     if(_client.connect(cServer, port)){ 
     _client.println("GET " + url + " HTTP/1.1"); 
     _client.println("Host: " + server); 
     _client.println(); 

     while (_client.available()) { 
      char c = _client.read(); 
      response = response + c; 
     } 
     } 
     Serial.println("inside"); 
     Serial.println(response); 
     return response; 
    } 

Und hier, wo ich versuche, die Bibliothek zu benutzen :

enthalten ich erhalte
#include <SPI.h> 
#include "ESP8266WiFi.h" 
#include <web.h> 

char ssid[] = "MYSID";  // your network SSID (name) 
char pass[] = "WIRELESSPWD"; 
int status = WL_IDLE_STATUS; 
WiFiClient* client; 
web webClient(*client); 

void setup() { 
    Serial.begin(9600); 
    while (!Serial) { 
    ; // wait for serial port to connect. Needed for native USB port only 
    } 

    while (status != WL_CONNECTED) { 
    Serial.print("Attempting to connect to SSID: "); 
    Serial.println(ssid); 
    status = WiFi.begin(ssid, pass); 
    delay(10000); 
    } 

    Serial.print("SSID: "); 
    Serial.println(WiFi.SSID()); 

    webClient.makeCall(); 
} 

void loop() { 

} 

die Fehler die folgenden, je nachdem, wo ich die & setzen zufällig, * usw., da ich nicht wirklich verstehe, was ich mache. Es kompiliert nie:

wifi_test:10: error: no matching function for call to 'web::web(WiFiClient&)' 


error: uninitialized reference member 'web::_client' [-fpermissive] 

    web::web(WiFiClient& client){ 
+3

Wenn Sie "dieses ganze" Pointer "vs." Referenz "vs." Value "Zeug verstehen wollen, kann ich Ihnen vorschlagen, ein C++ - Lehrbuch zu lesen? –

Antwort

1
class web { 
    private: 
    Client& _client; 
}; 

_client ist eine Referenz auf Client Objekt. Im Gegensatz zu einem Zeiger können Sie nicht ändern, wo die Referenz auf "zeigt". Sie müssen es also mit einem Wert initialisieren.

web::web(WiFiClient* client){ 
    _client = client; 
    } 

In Ihrem Konstruktor Sie nicht initialisieren Ihre _client Variable, aber sie versuchen es, einen Wert zuzuweisen. Das ist, warum Sie einen Fehler

error: uninitialized reference member 'web::_client'

erhalten einen Verweis initialisieren Sie Liste im Konstruktor verwenden initialisieren. Hier ist eine vereinfachte Version, die auch nur einen Konstruktor verwendet, da Sie nicht beide Überladungen haben müssen.

WiFiClient client; 
web webClient(client); 

ich Sie über Referenzen und Zeiger lesen vorschlagen, wenn Sie wollen, effektiv nutzen:

class web { 
    public: 
    web(Client& client); 
    void makeCall(); 
    private: 
    Client& _client; 
    String getRequest(String server, int port, String url); 
}; 

web::web(Client& client) 
: _client(client) 
{ 
} 

Dann können Sie ein web-Objekt erstellen. Sonst wirst du ständig Probleme mit ihnen haben.

+0

Danke, das hat funktioniert! Weißt du, wie man diesen _client definiert?web :: web (Client & Client): _client (client) <- Ich würde gerne mehr darüber lesen. – Doug

+0

@Doug Es heißt [Mitglied Initialisierungsliste] (http://en.cppreference.com/w/cpp/language/initializer_list). Im Prinzip ist das die Art, wie Member-Variablen in einem Konstruktor initialisiert werden. Wenn Sie es wie im '{}' Block schreiben, werden die Mitglieder zuerst mit ihren Standardwerten initialisiert und dann einen neuen Wert zugewiesen. Was nicht für Referenzen und Const-Mitglieder funktioniert. – rozina

0

Ihre Übersetzungsfehler ist ein Missbrauch des ‚*‘ Operator im Ausdruck

web webClient(*client); 

Was bedeutet für Sie schrieb: an der Adresse einen Verweis des Objekts an den Konstruktor senden "Klient". Wenn Sie das Zeichen '*' entfernen, sollte dieser spezielle Fehler verschwinden.