Có bao nhiêu dòng mã trong chương trình sau đây?
#include <iostream>
int main()
{
std::cout << "Hello, world!\n";
return 0;
}
Bạn có thể đã trả lời 7 (hoặc 6 nếu bạn không đếm dòng trống hoặc 4 nếu bạn không đếm số lần niềng răng).
Trình biên dịch của bạn, tuy nhiên, thấy một cái gì đó rất khác nhau:
~$ cpp hello.cpp | wc
18736 40822 437015
Vâng, đó là 18,7 KLOC chỉ cho một "Xin chào, thế giới!" chương trình. Trình biên dịch C ++ phải phân tích tất cả điều đó. Đây là một lý do chính tại sao quá trình biên dịch C ++ mất nhiều thời gian so với các ngôn ngữ khác và tại sao các ngôn ngữ hiện đại lại tránh các tệp tiêu đề.
Một câu hỏi tốt hơn sẽ là
Tại sao không C ++ có tập tin tiêu đề?
C ++ được thiết kế để trở thành siêu bộ của C, vì vậy nó phải giữ các tệp tiêu đề để tương thích ngược.
OK, vậy tại sao C có tệp tiêu đề?
Bởi vì mô hình biên dịch riêng biệt nguyên thủy của nó. Các tệp đối tượng được tạo bởi trình biên dịch C không bao gồm bất kỳ thông tin loại nào, vì vậy để ngăn ngừa lỗi loại, bạn cần đưa thông tin này vào mã nguồn của mình.
~$ cat sqrtdemo.c
int main(void)
{
/* implicit declaration int sqrt(int) */
double sqrt2 = sqrt(2);
printf("%f\n", sqrt2);
return 0;
}
~$ gcc -Wall -ansi -lm -Dsqrt= sqrtdemo.c
sqrtdemo.c: In function ‘main’:
sqrtdemo.c:5:5: warning: implicit declaration of function ‘printf’ [-Wimplicit-function-declaration]
sqrtdemo.c:5:5: warning: incompatible implicit declaration of built-in function ‘printf’ [enabled by default]
~$ ./a.out
2.000000
Thêm khai báo kiểu thích hợp sẽ sửa lỗi:
~$ cat sqrtdemo.c
#undef printf
#undef sqrt
int printf(const char*, ...);
double sqrt(double);
int main(void)
{
double sqrt2 = sqrt(2);
printf("%f\n", sqrt2);
return 0;
}
~$ gcc -Wall -ansi -lm sqrtdemo.c
~$ ./a.out
1.414214
Lưu ý rằng không có #include
s. Nhưng khi bạn sử dụng một số lượng lớn các chức năng bên ngoài (mà hầu hết các chương trình sẽ làm), việc khai báo chúng theo cách thủ công sẽ trở nên tẻ nhạt và dễ bị lỗi. Sử dụng tập tin tiêu đề dễ dàng hơn nhiều.
Làm thế nào là ngôn ngữ hiện đại có thể tránh các tập tin tiêu đề?
Bằng cách sử dụng một định dạng tệp đối tượng khác nhau bao gồm thông tin loại. Ví dụ, định dạng tệp Java *. Class bao gồm "mô tả" chỉ định các loại trường và tham số phương thức.
Đây không phải là một phát minh mới. Trước đó (1987), khi Borland thêm các "đơn vị" được biên dịch riêng cho Turbo Pascal 4.0, nó đã chọn sử dụng *.TPU
định dạng mới thay vì Turbo C *.OBJ
để loại bỏ nhu cầu về tệp tiêu đề.