2009-10-14 38 views
8

Mã sau có hợp pháp C++ hay không?Khai báo nhưng không xác định cấu trúc bên trong/lớp - hợp pháp C++ hay không?

class Foo 
{ 
    class Bar; 

    void HaveADrink(Bar &bar); 
    void PayForDrinks(Bar &bar); 

    public: 
    void VisitABar(int drinks); 
}; 

class Foo::Bar 
{ 
    public: 
    int countDrinks; 
}; 

void Foo::HaveADrink(Bar &bar) 
{ 
    bar.countDrinks++; 
} 
void Foo::PayForDrinks(Bar &bar) 
{ 
    bar.countDrinks = 0; 
} 
void Foo::VisitABar(int drinks) 
{ 
    Bar bar; 
    for (int i=0; i<drinks; i++) HaveADrink(bar); 
    PayForDrinks(bar); 
} 

Cả Visual C++ và GCC đều chấp nhận nó, tuy nhiên mã có vẻ lạ và tôi ghét phải từ chối bởi một số trình biên dịch trong tương lai. Tuy nhiên, mô hình có vẻ hữu ích với tôi để giảm phụ thuộc thời gian biên dịch - Tôi thường sử dụng nó để khai báo cấu trúc được sử dụng để truyền một số ngữ cảnh (một loạt các biến) được chia sẻ giữa một vài hàm trong cùng một tệp cpp, và theo cách này tôi không phải giới thiệu định nghĩa "ngữ cảnh" vào giao diện công cộng.

+0

Tôi chỉ đang trong quá trình tạo một vài lớp ngữ cảnh, vì vậy tôi cũng quan tâm. BTW, làm cho countDrinks có thể truy cập công cộng. – stefaanv

+0

Tôi có giả định rằng bạn đang đề cập đến định nghĩa 'class Foo :: Bar' không? – MSalters

Trả lời

10

hợp pháp và thực sự hữu ích để ẩn chi tiết triển khai cho thế giới bên ngoài.

9

[edit] Tôi đã nói đây là "thành ngữ pimpl": http://c2.com/cgi/wiki?PimplIdiom nhưng tôi đồng ý rằng đây chỉ là một phần của pimpl. Kỹ thuật này được sử dụng bởi pimpl.

Bạn đang chuyển tiếp lớp học Bar bên trong lớp Foo. Hoàn toàn hợp pháp miễn là bạn không làm bất cứ điều gì bên trong definigino của Foo mà sẽ yêu cầu sizeof Bar. Bạn có thể tham khảo Thanh bằng cách sử dụng con trỏ hoặc tham chiếu (Bar * hoặc Bar &), nhưng nếu bạn khai báo thành viên dữ liệu trong Foo như sau:

riêng: Bar _bar;

Nó sẽ không hoạt động. Lý do là vì định nghĩa của Foo phải đủ để xác định sizeof Foo. Vì kích thước của Bar không rõ trong định nghĩa của Foo, nó sẽ làm cho kích thước của Foo không xác định. Nhưng sử dụng con trỏ sẽ hoạt động:

riêng: Bar * _bar;

Vì kích thước của con trỏ giống nhau, và do đó được biết, bất kể Bar sẽ được định nghĩa sau đó như thế nào.

+2

Vâng, nó không phải là _exactly_ thành ngữ pimpl (không có pimpl trong mã của anh ta), nhưng bạn đúng - về cơ bản nó là. +1 – sbi

+1

Nó chỉ liên quan đến pimpl, vì nó là nhiều hơn về phạm vi của một số bối cảnh, nơi pimpl là việc thực hiện đầy đủ các lớp học của bạn. Nhưng bạn nói đúng: bạn chỉ có thể khai báo một con trỏ khi làm điều này. Làm cho bạn một ưu và sử dụng con trỏ thông minh thích hợp. – stefaanv

+0

Chắc chắn không phải PIMPL. Không có triển khai trong Bar. –

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