Frage

Ich habe Klasse Phänotypen mit dem folgenden Konstruktor:

Phenotype(uint8 init[NUM_ITEMS]);

kann ich einen Phänotyp wie diese erstellen:

uint8 data[] = {0,0,0,0,0};
Phenotype p(data);

Aber ich einen Fehler, wenn ich versuche, eine wie diese zu erstellen:

Phenotype p = {0,0,0,0,0};

Ausgabe:

$ make
g++ -Wall -g main.cpp -std=c++0x
main.cpp: In function ‘int main(int, char**)’:
main.cpp:109: error: no matching function for call to ‘Phenotype::Phenotype(<brace-enclosed initializer list>)’
main.cpp:37: note: candidates are: Phenotype::Phenotype(uint8*)

Der Fehler scheint darauf hinzudeuten, dass es einen Weg gibt, einen Konstruktor zu definieren, die eine Klammer geschlossene Initialisiererliste nimmt. Wer weiß, wie dies geschehen könnte?

War es hilfreich?

Lösung

Es kann nur für Aggregate erfolgen (Arrays und bestimmte Klassen. Entgegen der landläufigen Meinung, das funktioniert für viele nonpods auch). Schreiben einen Konstruktor, der sie nimmt, ist nicht möglich.

Da Sie es als „C ++ 0x“ markiert, dann ist dies möglich, wenn. Die magischen Worte „Initialisierer-Liste Konstruktor“. Dies geht wie

Phenotype(std::initializer_list<uint8> c) {
  assert(c.size() <= std::size(m_array));
  std::copy(c.begin(), c.end(), m_array);
}

// used like
Phenotype p1{1, 2, 3};
Phenotype p2({1, 3, 2}); // works too
Phenotype p3(1, 2, 3); // doesn't work

Allerdings wird eine solche Initialisierung Standard, um das Array konstruieren und verwenden dann den Zuweisungsoperator. Wenn Sie Geschwindigkeit und Sicherheit Ziel (Sie Kompilierung Fehler erhalten zu viele Initialisierer!), Können Sie auch einen gewöhnlichen Konstruktor mit einer variadische Vorlage verwenden.

Dies kann mehr generisch sein, als benötigt aber (oft ein initializer_list völlig ausreichend, vor allem für Normal ganze Zahlen). Es profitiert von perfekter Weiterleitung, so dass ein R-Wert Argument in ein Array-Element aufgebaut sein, bewegen kann

template<typename ...T>
Phenotype(T&&...t):m_array{ std::forward<T>(t)... } {

}

// used like
Phenotype p1{1, 2, 3}; 
Phenotype p2(1, 2, 3); // works too
Phenotype p3({1, 2, 3}); // doesn't work   

Es ist eine harte Wahl!

Bearbeiten Korrektur funktioniert die letzten auch, da wir nicht den Konstruktor explicit gemacht haben, so dass er den Kopierkonstruktor von Phenotype verwenden kann, ein temporäres Phenotype Objekt konstruieren und kopieren Sie sich über zu p3 . Aber das ist nicht das, was wir wirklich die Anrufe sein wollen würde:)

Andere Tipps

In C ++ 0x es scheint, dass Sie einen Konstruktor für diese erstellen können. Ich habe keine Erfahrung mit ihm selbst, aber es sieht aus wie Initialisiererliste-Konstruktor .

  

Ein Container kann einen Initialisierer-Liste Konstruktor wie diese implementieren:

template<class E> class vector {
public:
    vector (std::initializer_list<E> s) // initializer-list constructor
    {
        reserve(s.size());  // get the right amount of space
        uninitialized_copy(s.begin(), s.end(), elem);   // initialize elements (in elem[0:s.size()))
        sz = s.size();  // set vector size
    }

    // ... as before ...
};

Sie müssen die std :: initializer_list Vorlagentyp verwenden. Beispiel:

#include <iostream>
class X {
    public:
        X (std::initializer_list<int> list) {
        for (auto i = list.begin(); i != list.end(); i++) {
                std::cout << *i << std::endl;
            }
        }
};


int main () {
    X x = {1,2,3,4,5};
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top