2010-11-07 31 views
38

tôi có lớp học kiểu hình với các nhà xây dựng sau đây:Brace-kèm theo danh sách initializer constructor

Phenotype(uint8 init[NUM_ITEMS]); 

tôi có thể tạo ra một kiểu hình như thế này:

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

Nhưng tôi nhận được một lỗi khi tôi cố gắng tạo một như thế này:

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

Output:

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

Lỗi này dường như chỉ ra rằng có một cách để xác định một hàm tạo có danh sách khởi tạo kèm cặp ngoặc nhọn. Có ai biết làm thế nào điều này có thể được thực hiện?

+0

có thể trùng lặp [chúng ta có thể chuyển mảng làm đối số cho hàm theo cú pháp này, trong tiêu chuẩn C++ 0x sắp tới không?] (Http://stackoverflow.com/questions/3424727/can-we- pass-array-as-arguments-to-functions-by-this-syntax-under-coming-c0x) – kennytm

Trả lời

66

Nó chỉ có thể được thực hiện cho tổng hợp (mảng và các lớp nhất định. Trái ngược với niềm tin phổ biến, điều này làm việc cho nhiều nonpods quá). Viết một hàm tạo không cần đến chúng.

Vì bạn đã gắn thẻ nó là "C++ 0x", thì điều này là có thể. Từ ma thuật là "hàm tạo danh sách khởi tạo". Điều này giống như

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 

Tuy nhiên, việc khởi tạo đó sẽ mặc định tạo mảng và sau đó sử dụng toán tử gán. Nếu bạn nhằm mục đích cho tốc độ và sự an toàn (bạn nhận được các lỗi thời gian biên dịch cho quá nhiều initializers!), Bạn cũng có thể sử dụng một constructor bình thường với một mẫu variadic.

Điều này có thể chung chung hơn mặc dù cần thiết (thường là một initializer_list hoàn toàn đủ, đặc biệt là cho số nguyên đơn giản). Nó có lợi từ việc chuyển tiếp hoàn hảo, để một đối số rvalue có thể được di chuyển được xây dựng thành một phần tử mảng

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 

Đó là một lựa chọn khó!

Sửa Correction, người cuối cùng làm việc quá, như chúng ta đã không làm cho các nhà xây dựng explicit, vì vậy nó có thể sử dụng các nhà xây dựng bản sao của Phenotype, xây dựng một đối tượng tạm thời Phenotype và sao chép nó sang p3. Nhưng đó không phải là những gì chúng tôi thực sự muốn các cuộc gọi là :)

+0

Rất hữu ích. Được tìm kiếm xung quanh để trả lời câu hỏi này trong một thời gian –

+2

Ông đã gắn thẻ nó là C++ 11. Nhưng làm thế nào đến nó không hoạt động trong c + + 11? –

6

Trong C++ 0x có vẻ như bạn có thể tạo một hàm tạo cho việc này. Tôi không có kinh nghiệm với nó bản thân mình, nhưng có vẻ như nó được gọi là initializer list-constructor.

Một container có thể thực hiện một constructor khởi tạo danh sách như thế này:

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

Bạn cần phải sử dụng std :: initializer_list mẫu loại. Ví dụ:

#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}; 
} 
Các vấn đề liên quan