So übergeben Sie ein Argument in einem Singleton

So übergeben Sie ein Argument in einem Singleton

Sie müssen die Instanz von Singleton nicht dynamisch zuweisen. Das könnte so aussehen (manchmal auch als "Lazy Loading Singleton" bezeichnet ~ die Instanz wird spät &irgendwie "automatisch" erstellt):

#include <iostream>
#include <string>

class Questionnary
{
private:
    // constructor taking string:
    Questionnary(const std::string& name) : name_(name) { }
public:
    static Questionnary& getInstance(const std::string& name)
    {
        static Questionnary q(name);
        std::cout << "My name is: " << q.name_ << std::endl;
        return q;
    }
private:
    std::string name_;
};

int main() {
    Questionnary::getInstance("Josh");
    Questionnary::getInstance("Harry");
}

Ausgabe:

My name is: Josh
My name is: Josh

Beachten Sie, dass der Konstruktor nur einmal direkt aufgerufen wird, wenn getInstance wird zum ersten Mal aufgerufen.


Lassen Sie mich die Antwort von Martin York für Ihren Anwendungsfall erweitern. Ich empfehle in dieser speziellen Situation die Verwendung von Zeigern für Argumente, da wir von seiner inhärenten Eigenschaft Gebrauch machen, dass er "leer" sein kann.

class Questionnary
{
  std::string _str;

  static Questionnary& getInstanceImpl(std::string* const s = nullptr)
  {
    static Questionnary instance{ s };
    return instance;
  }

  Questionnary(std::string* const s)
    : _str{ s ? move(*s) : std::string{} } // employ move ctor
  {
    if (nullptr == s)
      throw std::runtime_error{ "Questionnary not initialized" };
  }

public:
  static Questionnary& getInstance()
  {
    return getInstanceImpl();
  }
  static void init(std::string s) // enable moving in
  {
    getInstanceImpl(&s);
  }

  Questionnary(Questionnary const&) = delete;
  void operator=(Questionnary const&) = delete;
};

Ich finde diesen Ansatz weniger verwirrend, da Sie die Instanz nach der ersten Initialisierung ohne (ohnehin verworfene) Argumente erhalten:

// first init
Questionnary::init("my single Questionnary");

// later on ...
Questionnary& q = Questionnary::getInstance();

Bearbeiten :Argument aus getInstance-Funktion und einige Optimierungen entfernt.


Haben Sie eine Methode, um die Instanz zu erstellen, um Argumente an den Konstruktor zu übergeben, und Sie könnten in der getInstance()-Methode behaupten, wenn CreateInstance nicht vor dem Aufruf aufgerufen wurde. Wie:

class Questionnary
{
private:
    // constructor taking string:
    Questionnary(const std::string& name) : name_(name) 
    {
        std::cout << "My name is: " << q.name_ << std::endl; 
    }

    static Questionnary* m_instance;
public:
    static void createInstance(const std::string& name)
    {
        assert(!m_instance);
        m_instance = new Questionary(name);
    }

    static void destroyInstance()
    {
        assert(m_instance);
        delete m_instance;
    }

    static Questionnary* Questionnary::getInstance()
    {
        assert(m_instance);
        return m_instance;
    }
private:
    std::string name_;
};