Search code examples
ooparduinoesp32arduino-c++

Not able to instanciate class


I am a beginner in C++. So please bear with me:

I try to write code for a temperature sensor which should post values to an API.

I am not able to instantiate my class ApiClient. I always get these errors:

  • IDE: call of an object of a class type without appropriate operator() or conversion functions to pointer-to-function type
  • IDE: no instance of overloaded function "ApiClient::ApiClient" matches the specified type
  • COMPILER: no match for call to '(ApiClient) (String&)'

My code looks like this (slightly slimmed for easier reading):

main.cpp

#include <ApiClient.h>
ApiClient api;

void setup()
{
  Serial.begin(115200);
  String apiUrl = "https://myapi.com/api";
  api(apiUrl); // ERROR: raises call of an object of a class type without appropriate operator() or conversion functions to pointer-to-function type

}

void loop()
{

  String temp = "49";
  api.sendValue("temperature", temp);
}

ApiClient.h

#ifndef WebClient_h
#define WebClient_h

#include <Arduino.h>
#include <WiFi.h>
#include <esp_wps.h>
#include <HTTPClient.h>

class ApiClient
{
public:
  ApiClient(); // this is only added for testing
  ApiClient(String apiUrl); // it should always instanciate with url
  void sendValue(String key, String value);
  String _apiUrl;
private:
};

#endif

ApiClient.cpp

#include <ApiClient.h>

String _apiUrl;

HTTPClient http;

ApiClient::ApiClient(String apiUrl) // IDE says: "no instance of overloaded function "ApiClient::ApiClient" matches the specified type"
{
  this->_apiUrl = apiUrl;
  // some stuff to establish a connection
}

Solution

  • You are attempting to call a constructor on an already constructed object.

    This line fails:

    api(apiUrl);
    

    The call you are attempting fails because the compiler is looking for one of these functions:

    return_type APIClient::operator()(const String&);
    return_type APIClient::operator()(String); 
    return_type APIClient::operator()(String&);
    

    Your statement should be a declaration if you want your constructor to be called.

    ApiClient api(apiUrl);
    // or better in c++11:
    APIClient api{ apiUrl };
    

    Alternatively, you could create an initializer in ApiClient, that takes a single String as a parameter, something like this:

    class ApiClient
    {
    public:
        ApiClient() { ...}
        ApiClient(const String& s) { Initialize(s); }
        Initialize(const String& s) { do the work }
    
        ...
    };
    

    Be careful when providing both one-step and two steps initialization APIs in your classes. You'll need a proper reset function to avoid mix-ups when reinitializing with a new string.