2016-01-28 62 views
12

Tôi đang cố gắng để tạo ra một lớp lồng nhau cũng là một lớp con của mẹ:lớp con lồng nhau trong C++

struct X { struct Y : public X {}; }; 

Thật không may, điều này dường như không được cho phép trong C++, như g ++ tạo ra lỗi

error: invalid use of incomplete type 'struct X'

Tuy nhiên, mã thực tế của tôi có X như là một lớp templated:

template<typename T> struct X 
{ struct Y : public X {}; }; 

tôi nhận được thông báo tương tự , nhưng lần này chỉ là cảnh báo:

warning: invalid use of incomplete type 'struct X< T >'

Câu hỏi của tôi là: tại sao trường hợp cũ là bất hợp pháp, trong khi trường hợp templated chỉ đưa ra cảnh báo? Các phiên bản templated hoạt động chính xác như tôi mong đợi nó (Tôi có thể tạo ra các trường hợp của X<T>::Y, đúc chúng vào X<T>, và như vậy), nhưng cảnh báo có nghĩa là tôi không nên sử dụng nó? Tôi có thể gặp phải vấn đề gì nếu tôi bỏ qua cảnh báo?

+6

Tôi nghi ngờ bạn cũng sẽ gặp lỗi trong trường hợp thứ hai, khi bạn cố thực sự khởi tạo 'X' –

+0

Sử dụng khai báo chuyển tiếp X? – LiMuBei

+2

@LiMuBei, bạn không thể kế thừa từ lớp chưa hoàn thành (lớp được chuyển tiếp). đó chính là vấn đề. – StoryTeller

Trả lời

2

Về mặt kỹ thuật, theo như trình biên dịch có liên quan, cách bố trí của các cơ sở (X) không cần phải được biết cho đến khi mẫu (X) được instanciated. Và mẫu (X) có thể không được chứng minh trước khi nó được xác định đầy đủ. Tại thời điểm đó, nó được biết đến.

Cách đơn giản nhất để có được một lỗi từ mẫu của bạn là cố gắng istantiate Y bên X:

template<typename T> struct X { 
    struct Y : public X {}; 
    Y y; 
}; 

Trong các phiên bản trước của trình biên dịch, không có cảnh báo trong trường hợp đó bạn thể hiện, nhưng nó đã được bổ sung tại một số điểm. Đây là một cuộc thảo luận từ GCC bugtracker về việc cảnh báo có giả mạo hay không. Có một số sự không chắc chắn liệu điều này có được phép theo tiêu chuẩn hay không nhưng kết luận của họ là nó không được phép.

Vì vậy, cả hai trường hợp đều không được phép theo tiêu chuẩn, nhưng GCC vẫn tiếp tục làm việc với tiêu chuẩn này, vì nó có thể.

Yam Marcovic Cho biết cách X::Y có thể được xác định theo cách tuân thủ tiêu chuẩn. Ví dụ giống hệt tương tự được hiển thị trong trình gỡ lỗi gcc.

9

Để trả lời câu hỏi cơ bản: Bạn nhận được cảnh báo vì mẫu chưa được khởi tạo nên không làm phiền bất kỳ ai.

Cách khắc phục điều này, trong cả hai trường hợp, sẽ xác định X::Y tại điểm trong đó bố cục của X đã được biết và do đó bố cục của Y có thể được suy luận đúng cách. Bạn có thể làm:

struct X { struct Y; } 
struct X::Y {}; 
Các vấn đề liên quan