2014-05-22 17 views
7
#include <iostream> 
#include <type_traits> 


struct base_pod_t { 
    unsigned x; 
}; 

struct der_pod_t : public base_pod_t { }; 

int main() 
{ 
    std::cout << "base_pod_t is POD: " << std::is_pod<base_pod_t>::value << std::endl; 
    std::cout << "der_pod_t is POD: " << std::is_pod<der_pod_t>::value << std::endl; 
    base_pod_t b1 = {};  // OK 
    base_pod_t b2 = {3}; // OK 

    der_pod_t p1 = {};  // OK 
// der_pod_t p2 = {4}; // ERROR! 
} 

Kết quả cuối cùng là lỗi. Làm thế nào tôi có thể khởi tạo cú pháp der_pod_t với giá trị?khởi tạo cú đúp cho nhóm được thừa kế


Dường như đó là POD mà nó cố gắng sử dụng hàm tạo?


EDIT: Như @Praetorian và @dyb gợi ý nó là một POD do đó result of std::is_pod<der_pod_t>::value is correct.

+0

bạn có trình biên dịch không tuân thủ. g ++ 4.8.2 tạo ra một nhị phân có nghĩa rằng der_pod_t không phải là một loại POD –

+0

@ BЈовић gcc phiên bản 4.8.2 20131212 (Red Hat 4.8.2-7) (GCC) nói là một POD. – name

+0

Rõ ràng là một lỗi. gcc phiên bản 4.8.2 (Ubuntu 4.8.2-19ubuntu1) nói với nó là không. –

Trả lời

10

base_pod_t là một tổng hợp và khởi tạo nào bạn đang thực hiện là tổng khởi tạo.

Từ §8.5.1 [dcl.init.aggr]

Một tổng là một mảng hoặc một lớp học (khoản 9) không có nhà xây dựng người dùng cung cấp (12.1) , không có thành viên dữ liệu không bảo mật hoặc riêng tư nào (Điều 11), không có lớp cơ sở (Điều 10) và không có chức năng ảo (10.3).

Khi tổng hợp được khởi tạo bằng danh sách bộ khởi tạo, như được chỉ rõ trong 8.5.4, các phần tử của danh sách khởi tạo được dùng làm khởi tạo cho các thành viên của tổng hợp, tăng chỉ số hoặc thứ tự thành viên. Mỗi thành viên được sao chép-khởi tạo từ điều khoản khởi tạo tương ứng. ...

Tuy nhiên, der_pod_t không phải là tổng hợp vì nó có lớp cơ sở. Đó là POD và các quy tắc tương tự cho việc khởi tạo danh sách không áp dụng. Bây giờ, khi trình biên dịch nhìn thấy một không trống rỗng braced-init-list, trước tiên nó sẽ tìm kiếm một hàm tạo có một initializer_list. Nếu không tìm thấy nó sau đó cố gắng để phù hợp với các nhà xây dựng khác của lớp. Vì der_pod_t không có hàm tạo nào lấy một đối số int, nên lỗi xảy ra.

+0

Tôi chỉ đọc tiêu chuẩn và chính xác như bạn nói. POD không thể kế thừa (§9.0.10 §9.0.7 viên đạn thứ 2). Cảm ơn. – name

+0

@name Bạn đang trích dẫn phiên bản tiêu chuẩn nào? Tôi thấy không có gì trong N3936 nói rằng 'der_pod_t' là * không * POD. 'der_pod_t' * là * bố cục tiêu chuẩn vì lớp cơ sở của nó cũng là bố cục chuẩn. Nó thỏa mãn cả hai lớp * tầm thường * và * bố cục tiêu chuẩn *, do đó nó là một POD. – Praetorian

+0

Nó là một POD. Tôi nhớ tiêu chuẩn giải thích. Cảm ơn. – name

0

Tôi đã giải quyết vấn đề này ngày hôm nay và tìm ra giải pháp cho nó, mặc dù tôi không thể nhấn mạnh mức độ nguy hiểm của giải pháp này (xem dưới đây tại sao lại nguy hiểm).

Vấn đề cụ thể của tôi là tôi chỉ muốn mở rộng cấu trúc thư viện với một số phương pháp của riêng mình. Tôi muốn giữ nó POD với chính xác cùng một bố trí như cơ sở kể từ khi tôi muốn sử dụng chức năng mà cơ sở như tham số.

Các giải pháp đi như thế này:

#include <iostream> 
using namespace std; 

struct BASE { 
    int x, y; 
}; 

struct FOO: BASE { 
    void Foo() { x = y = 1; } 
}; 

int main() { 
    // const declaration 
    const BASE a = { 0, 1 }; 
    const FOO &b = *reinterpret_cast<const FOO *> (&a); 

    // non-const declaration 
    BASE _a = { 0, 3 }; 
    FOO &c = *reinterpret_cast<FOO *> (&_a); 

    cout << "base: " << a.x << ", " << a.y << endl; 
    cout << "foo 1: " << b.x << ", " << b.y << endl; 
    cout << "foo 2: " << c.x << ", " << c.y << endl; 

    return 0; 
} 

Tuy nhiên, lưu ý rằng chỉ các công trình này bởi vì cách bố trí dữ liệu giữa BASE và FOO là như nhau. Cũng chỉ vì tôi sử dụng con trỏ để đúc thành kiểu FOO. Trong trường hợp này, việc tạo kiểu được thực hiện mà không có bất kỳ hàm tạo nào, nó chỉ giả vờ rằng bộ nhớ có định dạng đúng. Nếu bạn cố gắng reinterpret_cast mà không có con trỏ, trình biên dịch sẽ cố gắng xây dựng một đối tượng mới dựa trên bản gốc.

Xem this answer để có giải thích tốt hơn.

Thật không may, dường như không có một lớp lót đẹp cho việc này.Một macro thích hợp cho các khai báo có vẻ theo thứ tự.

Các vấn đề liên quan