Tại sao C ++ cần một tệp tiêu đề riêng?


138

Tôi chưa bao giờ thực sự hiểu tại sao C ++ cần một tệp tiêu đề riêng biệt có cùng chức năng như trong tệp .cpp. Nó làm cho việc tạo các lớp và tái cấu trúc chúng trở nên rất khó khăn và nó thêm các tệp không cần thiết vào dự án. Và sau đó là vấn đề với việc phải bao gồm các tệp tiêu đề, nhưng phải kiểm tra rõ ràng nếu nó đã được bao gồm.

C ++ đã được phê chuẩn vào năm 1998, vậy tại sao nó được thiết kế theo cách này? Những lợi thế nào có một tệp tiêu đề riêng biệt có?


Theo dõi câu hỏi:

Làm thế nào để trình biên dịch tìm thấy tệp .cpp với mã trong đó, khi tất cả những gì tôi đưa vào là tệp .h? Liệu nó có giả định rằng tệp .cpp có cùng tên với tệp .h hoặc nó thực sự xem qua tất cả các tệp trong cây thư mục?


2
Nếu bạn muốn chỉnh sửa một tập tin duy nhất, hãy kiểm tra lzz (www.lazycplusplus.com).
Richard Corden

Câu trả lời:


105

Bạn dường như đang hỏi về việc tách các định nghĩa khỏi các khai báo, mặc dù có các cách sử dụng khác cho các tệp tiêu đề.

Câu trả lời là C ++ không "cần" cái này. Nếu bạn đánh dấu mọi thứ nội tuyến (dù sao cũng là tự động cho các hàm thành viên được xác định trong định nghĩa lớp), thì không cần phải phân tách. Bạn chỉ có thể xác định mọi thứ trong các tập tin tiêu đề.

Những lý do bạn có thể muốn tách ra là:

  1. Để cải thiện thời gian xây dựng.
  2. Để liên kết với mã mà không có nguồn cho các định nghĩa.
  3. Để tránh đánh dấu mọi thứ "nội tuyến".

Nếu câu hỏi chung hơn của bạn là "tại sao C ++ không giống với Java?", Thì tôi phải hỏi, "tại sao bạn lại viết C ++ thay vì Java?" ;-p

Mặc dù vậy, nghiêm trọng hơn, lý do là trình biên dịch C ++ không thể tiếp cận với một đơn vị dịch thuật khác và tìm ra cách sử dụng các ký hiệu của nó, theo cách mà javac có thể và thực hiện. Tệp tiêu đề là cần thiết để khai báo cho trình biên dịch những gì nó có thể mong đợi có sẵn tại thời điểm liên kết.

Vì vậy, #includelà một thay thế văn bản thẳng. Nếu bạn xác định mọi thứ trong các tệp tiêu đề, bộ xử lý trước sẽ tạo ra một bản sao và dán khổng lồ của mọi tệp nguồn trong dự án của bạn và đưa dữ liệu đó vào trình biên dịch. Thực tế là tiêu chuẩn C ++ đã được phê chuẩn vào năm 1998 không liên quan gì đến vấn đề này, thực tế là môi trường biên dịch cho C ++ dựa rất nhiều vào C.

Chuyển đổi ý kiến ​​của tôi để trả lời câu hỏi tiếp theo của bạn:

Trình biên dịch tìm tệp .cpp với mã trong đó như thế nào

Nó không, ít nhất là tại thời điểm nó biên dịch mã đã sử dụng tệp tiêu đề. Các hàm bạn liên kết với thậm chí không cần phải được viết, đừng bận tâm đến trình biên dịch biết .cppchúng sẽ ở trong tệp nào. Mọi thứ mà mã gọi cần biết tại thời gian biên dịch được thể hiện trong khai báo hàm. Tại thời điểm liên kết, bạn sẽ cung cấp một danh sách các .otệp, hoặc các thư viện tĩnh hoặc động và tiêu đề có hiệu lực là một lời hứa rằng các định nghĩa của các hàm sẽ ở đó ở đâu đó.


3
Để thêm vào "Lý do bạn có thể muốn tách là:" & Tôi nghĩ chức năng quan trọng nhất của tệp tiêu đề là: Để tách thiết kế cấu trúc mã khỏi thực thi, bởi vì: A. Khi bạn vào các cấu trúc thực sự phức tạp có liên quan đến nhiều đối tượng, nó dễ dàng hơn nhiều để sàng lọc thông qua các tệp tiêu đề và nhớ cách chúng hoạt động cùng nhau, được bổ sung bởi các nhận xét tiêu đề của bạn. B. Một người không quan tâm đến việc xác định tất cả các cấu trúc đối tượng và một số người khác đang quan tâm đến việc thực hiện nó sẽ giữ mọi thứ có tổ chức. Trên tất cả tôi nghĩ rằng nó làm cho mã phức tạp dễ đọc hơn.
Andres Canella

Nói một cách đơn giản nhất, tôi có thể nghĩ đến sự hữu ích của việc tách tệp tiêu đề so với tệp cpp là tách Giao diện so với triển khai thực sự giúp ích cho các dự án trung bình / lớn.
Krishna Oza

Tôi dự định đưa vào (2), "liên kết với mã mà không có định nghĩa". OK, vì vậy bạn vẫn có thể có quyền truy cập vào git repo với các định nghĩa trong, nhưng vấn đề là bạn có thể biên dịch mã riêng biệt với việc triển khai các phụ thuộc của nó và sau đó liên kết. Nếu theo nghĩa đen, tất cả những gì bạn muốn là tách giao diện / triển khai thành các tệp khác nhau, không cần quan tâm đến việc xây dựng riêng biệt, thì bạn có thể làm điều đó bằng cách chỉ cần foo_interface.h bao gồm foo_imâyation.h.
Steve Jessop

4
@AndresCanella Không, không. Nó làm cho việc đọc và duy trì mã không phải của riêng bạn trở thành một cơn ác mộng. Để hiểu đầy đủ những gì làm trong mã, bạn cần chuyển qua 2n tệp thay vì n tệp. Đây không phải là ký hiệu Big-Oh, 2n tạo ra nhiều sự khác biệt so với chỉ n.
Błażej Michalik

1
Tôi thứ hai rằng đó là một lời nói dối mà tiêu đề giúp. kiểm tra nguồn minix chẳng hạn, thật khó để theo dõi nơi nó bắt đầu đến nơi kiểm soát được thông qua, nơi mọi thứ được khai báo / xác định .. nếu nó được xây dựng thông qua các mô-đun động tách biệt, nó sẽ được tiêu hóa bằng cách hiểu một điều sau đó nhảy đến một mô-đun phụ thuộc. thay vào đó, bạn cần phải theo dõi các tiêu đề và nó làm cho việc đọc bất kỳ mã nào được viết theo cách này là địa ngục. ngược lại, nodejs làm rõ nơi xuất phát mà không có ifdefs và bạn có thể dễ dàng xác định nơi đến từ đâu.
Dmitry

90

C ++ làm theo cách đó bởi vì C đã làm theo cách đó, vì vậy câu hỏi thực sự là tại sao C lại làm theo cách đó? Wikipedia nói một chút về điều này.

Các ngôn ngữ được biên dịch mới hơn (như Java, C #) không sử dụng khai báo chuyển tiếp; định danh được nhận dạng tự động từ các tệp nguồn và đọc trực tiếp từ các ký hiệu thư viện động. Điều này có nghĩa là các tập tin tiêu đề là không cần thiết.


12
+1 Đánh đinh vào đầu. Điều này thực sự không yêu cầu một lời giải thích dài dòng.
MSalters

6
Nó không đánh vào đầu tôi :( Tôi vẫn phải tìm hiểu tại sao C ++ phải sử dụng khai báo chuyển tiếp và tại sao nó không thể nhận ra mã định danh từ các tệp nguồn và đọc trực tiếp từ các ký hiệu thư viện động và tại sao C ++ lại làm vậy cách chỉ vì C đã làm theo cách đó: p
Alexander Taylor

2
Và bạn là một lập trình viên tốt hơn vì đã làm như vậy @AlexanderTaylor :)
Donald Byrd

66

Một số người coi các tệp tiêu đề là một lợi thế:

  • Nó được tuyên bố rằng nó cho phép / thực thi / cho phép tách giao diện và thực hiện - nhưng thông thường, đây không phải là trường hợp. Các tệp tiêu đề có đầy đủ các chi tiết triển khai (ví dụ: các biến thành viên của một lớp phải được chỉ định trong tiêu đề, mặc dù chúng không phải là một phần của giao diện chung) và các hàm có thể, và thường được định nghĩa là nội tuyến trong khai báo lớp trong tiêu đề, một lần nữa phá hủy sự tách biệt này.
  • Đôi khi nó được cho là cải thiện thời gian biên dịch vì mỗi đơn vị dịch thuật có thể được xử lý độc lập. Nhưng C ++ có lẽ là ngôn ngữ chậm nhất trong sự tồn tại khi nói đến thời gian biên dịch. Một phần của lý do là nhiều bao gồm nhiều lần lặp lại của cùng một tiêu đề. Một số lượng lớn các tiêu đề được bao gồm bởi nhiều đơn vị dịch thuật, yêu cầu chúng phải được phân tích cú pháp nhiều lần.

Cuối cùng, hệ thống tiêu đề là một vật phẩm từ những năm 70 khi C được thiết kế. Trước đó, máy tính có rất ít bộ nhớ và việc giữ toàn bộ mô-đun trong bộ nhớ không phải là một tùy chọn. Một trình biên dịch phải bắt đầu đọc tệp ở trên cùng, và sau đó tiến hành tuyến tính thông qua mã nguồn. Cơ chế tiêu đề cho phép điều này. Trình biên dịch không phải xem xét các đơn vị dịch thuật khác, nó chỉ cần đọc mã từ trên xuống dưới.

Và C ++ giữ lại hệ thống này để tương thích ngược.

Hôm nay, nó không có ý nghĩa. Đó là không hiệu quả, dễ bị lỗi và quá phức tạp. Có nhiều cách tốt hơn để phân tách giao diện và thực hiện, nếu đó là mục tiêu.

Tuy nhiên, một trong những đề xuất cho C ++ 0x là thêm một hệ thống mô-đun phù hợp, cho phép mã được biên dịch tương tự .NET hoặc Java, thành các mô-đun lớn hơn, tất cả trong một lần và không có tiêu đề. Đề xuất này đã không thực hiện cắt giảm trong C ++ 0x, nhưng tôi tin rằng nó vẫn thuộc danh mục "chúng tôi muốn thực hiện điều này sau". Có lẽ trong một TR2 hoặc tương tự.


Đây là câu trả lời tốt nhất trên trang. Cảm ơn bạn!
Chuck Le Mông

29

Theo hiểu biết của tôi (giới hạn - tôi không phải là nhà phát triển C thông thường), điều này bắt nguồn từ C. Hãy nhớ rằng C không biết các lớp hoặc không gian tên là gì, nó chỉ là một chương trình dài. Ngoài ra, các chức năng phải được khai báo trước khi bạn sử dụng chúng.

Ví dụ, sau đây sẽ cung cấp một lỗi biên dịch:

void SomeFunction() {
    SomeOtherFunction();
}

void SomeOtherFunction() {
    printf("What?");
}

Lỗi phải là "Một số chức năng khác không được khai báo" bởi vì bạn gọi nó trước khi khai báo. Một cách để khắc phục điều này là bằng cách di chuyển một số chức năng khác lên trên một số chức năng. Một cách tiếp cận khác là khai báo chữ ký hàm trước:

void SomeOtherFunction();

void SomeFunction() {
    SomeOtherFunction();
}

void SomeOtherFunction() {
    printf("What?");
}

Điều này cho phép trình biên dịch biết: Nhìn vào đâu đó trong mã, có một hàm gọi là someOtherFunction trả về void và không lấy bất kỳ tham số nào. Vì vậy, nếu bạn mã hóa mã cố gắng gọi cho một số chức năng khác, đừng hoảng sợ và thay vào đó hãy tìm kiếm nó.

Bây giờ, hãy tưởng tượng bạn có một số Hàm và Một số Hàm trong hai tệp .c khác nhau. Sau đó, bạn phải #include "someOther.c" trong some.c. Bây giờ, thêm một số chức năng "riêng tư" vào someOther.c. Vì C không biết các hàm riêng tư, nên hàm đó cũng sẽ có sẵn trong some.c.

Đây là nơi tệp .h xuất hiện: Chúng chỉ định tất cả các hàm (và biến) mà bạn muốn 'Xuất' từ tệp .c có thể được truy cập trong các tệp .c khác. Bằng cách đó, bạn có được một cái gì đó như phạm vi Công cộng / Riêng tư. Ngoài ra, bạn có thể cung cấp tệp .h này cho người khác mà không phải chia sẻ mã nguồn của mình - các tệp .h cũng hoạt động chống lại các tệp .lib đã biên dịch.

Vì vậy, lý do chính thực sự là để thuận tiện, để bảo vệ mã nguồn và để có một chút tách rời giữa các phần của ứng dụng của bạn.

Đó là C mặc dù. C ++ đã giới thiệu Các lớp và các bộ sửa đổi riêng / công khai, vì vậy trong khi bạn vẫn có thể hỏi xem chúng có cần thiết hay không, C ++ AFAIK vẫn yêu cầu khai báo các hàm trước khi sử dụng chúng. Ngoài ra, nhiều Nhà phát triển C ++ cũng đã hoặc đang phát triển C và tiếp quản các khái niệm và thói quen của họ cho C ++ - tại sao thay đổi những gì không bị phá vỡ?


5
Tại sao trình biên dịch không thể chạy qua mã và tìm tất cả các định nghĩa hàm? Có vẻ như một cái gì đó sẽ khá dễ dàng để lập trình vào trình biên dịch.
Marius

3
Nếu bạn nguồn, cái mà bạn thường không có. Biên dịch C ++ là mã máy hiệu quả với chỉ đủ thông tin bổ sung để tải và liên kết mã. Sau đó, bạn trỏ CPU vào điểm vào và để nó chạy. Điều này về cơ bản khác với Java hoặc C #, trong đó mã được biên dịch thành mã byte trung gian có chứa siêu dữ liệu trên nội dung của nó.
DevSolar

Tôi đoán rằng vào năm 1972, đó có thể là một hoạt động khá tốn kém cho trình biên dịch.
Michael Stum

Chính xác những gì Michael Stum nói. Khi hành vi này được xác định, quét tuyến tính thông qua một đơn vị dịch thuật là điều duy nhất có thể được thực hiện trên thực tế.
jalf

3
Yup - biên dịch trên 16 đắng với lưu trữ khối lượng băng là không tầm thường.
MSalters

11

Ưu điểm đầu tiên: Nếu bạn không có tệp tiêu đề, bạn sẽ phải bao gồm các tệp nguồn trong các tệp nguồn khác. Điều này sẽ khiến các tệp bao gồm được biên dịch lại khi tệp được bao gồm thay đổi.

Ưu điểm thứ hai: Nó cho phép chia sẻ các giao diện mà không chia sẻ mã giữa các đơn vị khác nhau (các nhà phát triển, nhóm, công ty khác nhau, v.v.)


1
Bạn có ngụ ý rằng, ví dụ như trong C # 'bạn sẽ phải bao gồm các tệp nguồn trong các tệp nguồn khác'? Bởi vì rõ ràng là bạn không. Đối với lợi thế thứ hai, tôi nghĩ đó là quá phụ thuộc ngôn ngữ: bạn sẽ không sử dụng các tệp .h trong ví dụ Delphi
Vlagged

Bạn phải biên dịch lại toàn bộ dự án, vậy lợi thế đầu tiên có thực sự được tính không?
Marius

ok, nhưng tôi không nghĩ rằng đó là một tính năng ngôn ngữ. Đó là một cái gì đó thực tế hơn để đối phó với khai báo C trước khi định nghĩa "vấn đề". Nó giống như một người nổi tiếng nói rằng "đó không phải là một lỗi mà là một tính năng" :)
neuro

@Marius: Vâng, nó thực sự có giá trị. Liên kết toàn bộ dự án khác với biên dịch & liên kết toàn bộ dự án. Khi số tập tin trong dự án tăng lên, việc biên dịch tất cả chúng trở nên thực sự khó chịu. @Vlagged: Bạn nói đúng, nhưng tôi không so sánh c ++ với ngôn ngữ khác. Tôi đã so sánh chỉ sử dụng các tệp nguồn so với sử dụng các tệp nguồn và tiêu đề.
erelender

C # không bao gồm các tệp nguồn trong các tệp khác, nhưng bạn vẫn phải tham chiếu các mô-đun - và điều đó làm cho trình biên dịch tìm nạp các tệp nguồn (hoặc phản ánh vào tệp nhị phân) để phân tích các ký hiệu mà mã của bạn sử dụng.
gbjbaanb

5

Sự cần thiết của các tệp tiêu đề xuất phát từ các giới hạn mà trình biên dịch có để biết về thông tin loại cho các hàm và hoặc các biến trong các mô-đun khác. Chương trình hoặc thư viện đã biên dịch không bao gồm thông tin loại mà trình biên dịch yêu cầu để liên kết với bất kỳ đối tượng nào được xác định trong các đơn vị biên dịch khác.

Để bù đắp cho giới hạn này, C và C ++ cho phép khai báo và những khai báo này có thể được đưa vào các mô-đun sử dụng chúng với sự trợ giúp của chỉ thị #include của bộ tiền xử lý.

Mặt khác, các ngôn ngữ như Java hoặc C # bao gồm thông tin cần thiết để liên kết trong đầu ra của trình biên dịch (tệp lớp hoặc tập hợp). Do đó, không còn cần phải duy trì các khai báo độc lập được bao gồm bởi các máy khách của một mô-đun.

Lý do cho thông tin ràng buộc không được bao gồm trong đầu ra của trình biên dịch là đơn giản: nó không cần thiết trong thời gian chạy (bất kỳ kiểm tra kiểu nào xảy ra tại thời gian biên dịch). Nó sẽ chỉ lãng phí không gian. Hãy nhớ rằng C / C ++ xuất phát từ thời điểm mà kích thước của một thư viện thực thi hoặc thư viện có vấn đề khá nhiều.


Tôi đồng ý với bạn. Tôi có ý tưởng tương tự ở đây: stackoverflow.com/questions/3702132/ từ
smwikipedia

4

C ++ được thiết kế để thêm các tính năng ngôn ngữ lập trình hiện đại vào cơ sở hạ tầng C, mà không cần thay đổi bất cứ điều gì về C mà không phải là ngôn ngữ cụ thể.

Vâng, tại thời điểm này (10 năm sau tiêu chuẩn C ++ đầu tiên và 20 năm sau khi nó bắt đầu phát triển nghiêm trọng về cách sử dụng), thật dễ dàng để hỏi tại sao nó không có một hệ thống mô-đun phù hợp. Rõ ràng bất kỳ ngôn ngữ mới nào được thiết kế ngày nay sẽ không hoạt động như C ++. Nhưng đó không phải là điểm của C ++.

Quan điểm của C ++ là mang tính tiến hóa, sự tiếp nối suôn sẻ của thực tiễn hiện tại, chỉ bổ sung các khả năng mới mà không (quá thường xuyên) phá vỡ những thứ hoạt động đầy đủ cho cộng đồng người dùng của nó.

Điều này có nghĩa là nó làm cho một số điều khó hơn (đặc biệt đối với những người bắt đầu một dự án mới) và một số điều dễ dàng hơn (đặc biệt đối với những người duy trì mã hiện tại) so với các ngôn ngữ khác sẽ làm.

Vì vậy, thay vì mong đợi C ++ biến thành C # (sẽ là vô nghĩa vì chúng ta đã có C #), tại sao không chọn công cụ phù hợp cho công việc? Bản thân tôi, tôi nỗ lực để viết các khối đáng kể của chức năng mới bằng ngôn ngữ hiện đại (tôi tình cờ sử dụng C #) và tôi có một lượng lớn C ++ hiện có mà tôi đang giữ trong C ++ vì sẽ không có giá trị thực sự khi viết lại nó tất cả. Dù sao thì chúng cũng tích hợp rất độc đáo, vì vậy nó hầu như không gây đau đớn.


Làm thế nào để bạn tích hợp C # và C ++? Qua COM?
Peter Mortensen

1
Có ba cách chính, "tốt nhất" phụ thuộc vào mã hiện tại của bạn. Tôi đã sử dụng cả ba. Mã tôi sử dụng nhiều nhất là COM vì mã hiện tại của tôi đã được thiết kế xung quanh nó, vì vậy nó thực sự liền mạch, hoạt động rất tốt đối với tôi. Ở một số nơi kỳ lạ, tôi sử dụng C ++ / CLI, giúp tích hợp cực kỳ trơn tru cho mọi tình huống khi bạn chưa có giao diện COM (và bạn có thể thích sử dụng giao diện COM hiện tại ngay cả khi bạn có chúng). Cuối cùng, có p / invoke về cơ bản cho phép bạn gọi bất kỳ hàm giống C nào được hiển thị từ DLL, vì vậy cho phép bạn gọi trực tiếp bất kỳ API Win32 nào từ C #.
Daniel Earwicker

4

Chà, C ++ đã được phê chuẩn vào năm 1998, nhưng nó đã được sử dụng lâu hơn thế rất nhiều và việc phê chuẩn chủ yếu là thiết lập việc sử dụng hiện tại thay vì áp đặt cấu trúc. Và vì C ++ dựa trên C và C có các tệp tiêu đề, C ++ cũng có chúng.

Lý do chính cho các tệp tiêu đề là để cho phép biên dịch các tệp riêng biệt và giảm thiểu các phụ thuộc.

Giả sử tôi có foo.cpp và tôi muốn sử dụng mã từ các tệp bar.h / bar.cpp.

Tôi có thể #inc loại "bar.h" trong foo.cpp, sau đó lập trình và biên dịch foo.cpp ngay cả khi bar.cpp không tồn tại. Tệp tiêu đề hoạt động như một lời hứa với trình biên dịch rằng các lớp / hàm trong bar.h sẽ tồn tại vào thời gian chạy và nó có mọi thứ cần biết.

Tất nhiên, nếu các chức năng trong bar.h không có cơ quan khi tôi cố gắng liên kết chương trình của mình, thì nó sẽ không liên kết và tôi sẽ gặp lỗi.

Một tác dụng phụ là bạn có thể cung cấp cho người dùng một tệp tiêu đề mà không tiết lộ mã nguồn của bạn.

Một cách khác là nếu bạn thay đổi việc triển khai mã của mình trong tệp * .cpp, nhưng hoàn toàn không thay đổi tiêu đề, bạn chỉ cần biên dịch tệp * .cpp thay vì mọi thứ sử dụng nó. Tất nhiên, nếu bạn đặt nhiều triển khai vào tệp tiêu đề, thì điều này trở nên ít hữu ích hơn.


3

Nó không cần một tệp tiêu đề riêng biệt có cùng chức năng như trong chính. Nó chỉ cần nó nếu bạn phát triển một ứng dụng bằng nhiều tệp mã và nếu bạn sử dụng một chức năng chưa được khai báo trước đó.

Đó thực sự là một vấn đề phạm vi.


1

C ++ đã được phê chuẩn vào năm 1998, vậy tại sao nó được thiết kế theo cách này? Những lợi thế nào có một tệp tiêu đề riêng biệt có?

Trên thực tế, các tệp tiêu đề trở nên rất hữu ích khi kiểm tra chương trình lần đầu tiên, kiểm tra các tệp tiêu đề (chỉ sử dụng trình soạn thảo văn bản) cung cấp cho bạn tổng quan về kiến ​​trúc của chương trình, không giống như các ngôn ngữ khác mà bạn phải sử dụng các công cụ tinh vi để xem các lớp và chức năng thành viên của họ.


1

Tôi nghĩ rằng thực (lịch sử) lý do đằng sau tập tin tiêu đề đã được đưa ra như dễ dàng hơn cho các nhà phát triển trình biên dịch ... nhưng sau đó, tập tin tiêu đề làm cho lợi thế.
Kiểm tra bài viết trước để biết thêm thảo luận ...


1

Chà, bạn hoàn toàn có thể phát triển C ++ mà không cần tệp tiêu đề. Trong thực tế, một số thư viện sử dụng nhiều mẫu không sử dụng mô hình tệp tiêu đề / mã (xem boost). Nhưng trong C / C ++, bạn không thể sử dụng cái gì đó không được khai báo. Một cách thực tế để đối phó với điều đó là sử dụng các tệp tiêu đề. Thêm vào đó, bạn có được lợi thế của việc chia sẻ mã / thực hiện chia sẻ giao diện. Và tôi nghĩ rằng nó không được hình dung bởi những người tạo C: Khi bạn sử dụng các tệp tiêu đề được chia sẻ, bạn phải sử dụng nổi tiếng:

#ifndef MY_HEADER_SWEET_GUARDIAN
#define MY_HEADER_SWEET_GUARDIAN

// [...]
// my header
// [...]

#endif // MY_HEADER_SWEET_GUARDIAN

đó không thực sự là một tính năng ngôn ngữ mà là một cách thực tế để đối phó với nhiều sự bao gồm.

Vì vậy, tôi nghĩ rằng khi C được tạo ra, các vấn đề về khai báo chuyển tiếp đã bị đánh giá thấp và bây giờ khi sử dụng một ngôn ngữ cấp cao như C ++, chúng ta phải đối phó với những thứ này.

Một gánh nặng khác cho chúng tôi người dùng C ++ nghèo ...


1

Nếu bạn muốn trình biên dịch tự động tìm ra các ký hiệu được xác định trong các tệp khác, bạn cần buộc lập trình viên đặt các tệp đó vào các vị trí được xác định trước (như cấu trúc gói Java xác định cấu trúc thư mục của dự án). Tôi thích các tập tin tiêu đề. Ngoài ra, bạn sẽ cần một trong hai nguồn thư viện bạn sử dụng hoặc một số cách thống nhất để đưa thông tin cần thiết của trình biên dịch vào nhị phân.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.