سؤال

لدي النمط الظاهري للصف مع المنشئ التالي:

Phenotype(uint8 init[NUM_ITEMS]);

يمكنني إنشاء النمط الظاهري مثل هذا:

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

لكنني أحصل على خطأ عندما أحاول إنشاء واحد مثل هذا:

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

انتاج:

$ 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*)

يبدو أن الخطأ يشير إلى أن هناك طريقة لتحديد مُنشئ يأخذ قائمة مُهيئ محفوظة. هل يعرف أحد كيف يمكن القيام بذلك؟

هل كانت مفيدة؟

المحلول

لا يمكن القيام به إلا للمجاميع (المصفوفات وبعض الفصول الدراسية. على عكس الاعتقاد الشائع ، فإن هذا يعمل للعديد من غير المرسوم أيضًا). كتابة مُنشئ يأخذها غير ممكن.

نظرًا لأنك وضعت علامة عليها على أنها "C ++ 0x" ، فهذا ممكن. الكلمات السحرية هي "مُنشئ قائمة التهيئة". هذا يذهب مثل

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

ومع ذلك ، فإن هذا التهيئة سوف تقوم ببناء الصفيف ثم استخدام مشغل المهمة. إذا كنت تهدف إلى السرعة والسلامة (يمكنك الحصول على أخطاء وقت الترجمة للعديد من عمليات التهيئة!) ، يمكنك أيضًا استخدام مُنشئ عادي مع قالب متغير.

يمكن أن يكون هذا أكثر عامة مما هو مطلوب (غالبًا ما تكفي initializer_list تمامًا ، خاصة بالنسبة للأعداد الصحيحة العادية). يستفيد من إعادة التوجيه المثالي ، بحيث يمكن نقل حجة rvalue إلى عنصر صفيف

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   

إنه خيار صعب!

يحرر تصحيح ، آخر واحد يعمل أيضًا ، لأننا لم نصنع المُنشئ explicit, ، بحيث يمكنه استخدام مُنشئ النسخ من Phenotype, ، بناء مؤقت Phenotype اعتراض ونسخه إلى p3. لكن هذا ليس ما نريد حقًا أن تكون عليه المكالمات :)

نصائح أخرى

في C ++ 0x يبدو أنه يمكنك إنشاء مُنشئ لهذا الغرض. ليس لدي أي خبرة معها بنفسي ، لكن يبدو أنه يسمى القائمة التهيئة القائمة.

قد تنفذ حاوية مُنشئ قائمة التهيئة مثل هذا:

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 ...
};

تحتاج إلى استخدام نوع قالب std :: pritializer_list. مثال:

#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};
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top