2012-03-02 40 views
19

Tôi là người mới bắt đầu với C++. Khi tôi viết mã đôi khi tôi viết #include <string> và mã hoạt động, lần khác tôi không viết #include <string> và mã không hoạt động. Nhưng đôi khi nó hoạt động mà không cần #include <string>.Tại sao bỏ sót "#include <string>" chỉ đôi khi gây ra lỗi biên dịch?

Vì vậy, tôi phải viết #include <string> để mã hoạt động?

+12

Mọi người, cái quái gì ?! Tất nhiên đây là một câu hỏi thực sự, hợp pháp! Nơi nào tất cả các downvotes và đóng phiếu đến từ đâu? Quay trở lại giường. –

+0

Bằng cách nào đó, trong tâm trí của tôi, câu hỏi này là hiệu quả như 'đây không phải là droids bạn đang tìm kiếm'. – karlphillip

+0

@Linus Hãy tiếp tục. –

Trả lời

14

Nếu bạn sử dụng các thành viên được khai báo bên trong tiêu đề tiêu chuẩn string thì có, bạn phải bao gồm tiêu đề đó trực tiếp hoặc gián tiếp (thông qua các tiêu đề khác).

Một số trình biên dịch trên một số nền tảng thể trên một số thời điểm tháng biên dịch ngay cả khi bạn thất bại trong việc bao gồm tiêu đề. Hành vi này không may, không đáng tin cậy và không có nghĩa là bạn không nên bao gồm tiêu đề.

Lý do đơn giản là bạn đã bao gồm các tiêu đề chuẩn khác mà cũng xảy ra để bao gồm string. Nhưng như tôi đã nói, điều này có thể nói chung không được dựa vào và nó cũng có thể thay đổi rất đột ngột (ví dụ, khi một phiên bản mới của trình biên dịch được cài đặt).

Luôn bao gồm tất cả các tiêu đề cần thiết. Thật không may, có vẻ như không phải là một tài liệu trực tuyến đáng tin cậy mà các tiêu đề cần được đưa vào. Tham khảo sách hoặc tiêu chuẩn C++ chính thức.

Ví dụ, đoạn mã sau biên dịch với trình biên dịch của tôi (gcc 4.6):

#include <iostream> 

int main() { 
    std::string str; 
} 

Nhưng nếu tôi loại bỏ các dòng đầu tiên, nó không còn biên dịch mặc dù iostream tiêu đề thực sự cần được liên quan.

+0

Bất kỳ ý tưởng nào cho dù điều đó xảy ra với các tệp tiêu đề khác với ''? –

+1

@ C.R. Nó chắc chắn không, rõ ràng, vì các tiêu đề tiêu chuẩn đôi khi sử dụng lẫn nhau. Ví dụ, 'std :: pair' được định nghĩa trong' 'nhưng có * không * triển khai thư viện chuẩn yêu cầu bạn bao gồm tiêu đề này nếu bạn đã bao gồm' 'vì sau này yêu cầu' std :: pair'. Điều này cũng đúng đối với các loại khác. Đây là một trong những điểm yếu lớn của hệ thống tiêu đề C++ so với hệ thống mô-đun thích hợp. –

+1

Về * Thật không may, có vẻ như không phải là tài liệu trực tuyến đáng tin cậy mà bạn cần phải bao gồm tiêu đề. * Bạn luôn có thể tìm kiếm những gì bạn đang sử dụng trên cppreference.com và nó sẽ cho bạn biết tiêu đề của nó. – NathanOliver

0

Nếu bạn chỉ sử dụng một con trỏ/tham chiếu đến một người sử dụng định nghĩa kiểu, loại chỉ cần được tuyên bố:

class my_class; 
void foo(const my_class& c); 

Nhưng khi bạn đang sử dụng giá trị, trình biên dịch cần phải biết kích thước và với định nghĩa của loại đó.

Và lưu ý rằng tiêu đề chuẩn có thể bao gồm các tiêu đề khác, không tự động có nghĩa là tất cả triển khai thực hiện điều đó, vì vậy bạn không thể dựa vào điều đó.

2

Có thể là tiêu đề khác mà bạn làm gồm có #include <string> trong đó. Tuy nhiên, thường là một ý tưởng hay khi #include <string> trực tiếp trong mã của bạn ngay cả khi không cần thiết cho việc xây dựng thành công, trong trường hợp các tiêu đề "khác" này thay đổi - ví dụ do trình biên dịch khác (hoặc phiên bản khác)/triển khai thư viện chuẩn, nền tảng hoặc thậm chí chỉ là cấu hình xây dựng.

(Tất nhiên, cuộc thảo luận này áp dụng cho bất kỳ tiêu đề nào, không chỉ <string>.)

2

Mặc dù, không có trực tiếp xuất hiện của #include <string> trong một file nguồn cụ thể, không có nghĩa là nó chưa được bao gồm bởi một tập tin tiêu đề. Xem xét việc này:

File: header.h

#if !defined(__HEADER_H__) 
#define __HEADER_H__ 

// more here 
#include <string> 
// ...and here 

#endif 

File: source1.cc

#include <string> 

void foo() 
{ 
    // No error here. 
    string s = "Foo"; 
} 

File: source2.cc

#include <header.h> 

void bar() 
{ 
    // Still no error, since there's a #include <string> in header.h 
    string s = "Bar"; 
} 

File: source3.cc

void zoid() 
{ 
    // Here's the error; no such thing as "string", since non of the 
    // previous headers had been included. 
    string s = "Zoid"; 
} 
0

Không đúng là chuỗi tiêu đề được bao gồm bởi các tiêu đề khác. Bản thân chuỗi tiêu đề chỉ bao gồm. Không có định nghĩa. Vì vậy, tất cả các định nghĩa cần thiết cần thiết cho việc sử dụng chuỗi nằm trong tiêu đề được bao gồm bởi chuỗi tiêu đề. Các tiêu đề này có thể đã được bao gồm bởi các tiêu đề khác. Sau đó, mọi thứ hoạt động. Ví dụ: ios tiêu đề bao gồm stringbuf, bao gồm ...

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