lundi 4 avril 2022

Clean methodology for passing ctor parameters from base class

Let me start by saying, that this is not an entirely new topic. There was a discussion here which re-affirmed what I thought was true, but I'm having difficulty putting it into practice.

Here is my scenario. I've tried to limit the code I am showing to what is relevant, please ask if you need to see more.

  • The config class just parses a json configuration and saves the current state on exit.

  • the Command class is the hardware device wrapper. It does the heavy lifting for the application. It dependency injects the config.

-Sync Manager, will eventually be the class responsible for making high level calls as well as being the base class for the public API. Command is dependency injected as it contains quite a few public and protected commands that I would like the sync manager to inherit. The code ran fine, with no issues until I added the private access specifier in command.h and added "public Command" to the SyncManager class.

There are two issues that are confusing me.

  1. I understand that because I do not have a default constructor for Command, I have to satisfy it's dependancies prior to calling SyncManager with this as a parameter, but isn't this already being done when I instantiate the SyncManager class with the commandWrapper object.

  2. While I was developing these classes, all members of Command were public, and I had no issues. Why does the act of protecting members and attempting to expose them to the SyncManager class cause this issue?

config.h

class Config 
{
  public:
  Config();

  virtual ~Config();

/* ... */

}

config.cpp

Config::Config()
{
  this->read();
}

Config::~Config()
{
  this->write();
}

command.h

class Command
{
  public:
  Command(std::shared_ptr<Config>);

  virtual ~Command();

  void setLightOn(const unsigned short _lightId, bool _on = true);

  bool setLightBrightness(const unsigned short _lightId, const unsigned short _value);

  bool setLightHue(const unsigned short _lightId, const unsigned short _value);

  bool setLightSaturation(const unsigned short _lightId, const unsigned short _value);

  bool setLightColorXY(const unsigned short _lightId, const float _x, float _y);

protected:
  bool refreshDataFromDevice(const unsigned short);

  bool setFieldAndSend(
    const std::string, 
    const std::string, 
    const unsigned int, 
    const Hue::HueFieldEnum, 
    std::string);

private:

/* ... */

}

command.cpp

Command::Command(std::shared_ptr<Config> _config) : mCfg(_config) 
{
  curl_global_init(CURL_GLOBAL_ALL);
  connect();

  for(int i = 0; i < deviceArraySize; ++i)
  {
    getDeviceData(i);
  }
}

Command::~Command()
{
  curl_global_cleanup();
}

syncManager.h

class SyncManager : public Command
{
    public:
    SyncManager(std::shared_ptr<Command>, std::shared_ptr<Hue::Device>);

    virtual ~SyncManager() = default;

    void runEventLoop(bool&);
    
    private:
    std::shared_ptr<Command> command;
    std::shared_ptr<Hue::Device> deviceState;

    std::vector<Task> taskVector;
};

syncManager.cpp

SyncManager::SyncManager(std::shared_ptr<Command>(_command), std::shared_ptr<Hue::Device>(_deviceState)) 
: command(_command), deviceState(_deviceState)
{
    // Debug
    Task tsk(6);
    taskVector.push_back(tsk);
}

main.cpp

int main()
{
  /* Signal traps for various inturrupts       */
  signal(SIGINT, sigHandler);  /* Ctrl + C     */
  signal(SIGQUIT, sigHandler); /* Ctrl + D     */
  signal(SIGHUP, sigHandler);  /* On pty close */
  signal(SIGTERM, sigHandler); /* On term sig  */

  auto configuration = std::make_shared<Config>();

  auto commandWrapper = std::make_shared<Command>(configuration);
  auto deviceData = std::make_shared<Hue::Device>();

  auto syncManager = std::make_shared<SyncManager>(commandWrapper, deviceData);

  auto tuiManagementConsole = std::make_shared<Console>(); 
  std::thread syncManagerThread(&SyncManager::runEventLoop, syncManager, std::ref(terminate));
  std::thread tuiManagementConsoleThread(&Console::runEventLoop, tuiManagementConsole, std::ref(terminate));

  tuiManagementConsoleThread.join();
  syncManagerThread.join();

  return 0;
}

error

error: constructor for 'SyncManager' must explicitly initialize the base class 'Command' which does not have a default constructor
SyncManager::SyncManager(std::shared_ptr<Command>(_command), std::shared_ptr<Hue::Device>(_deviceState)) 

Aucun commentaire:

Enregistrer un commentaire