Tầm quan trọng của tệp .inl trong C ++


108

Lợi ích của việc khai báo trong tệp .inl là gì? Khi nào tôi cần sử dụng cùng một?


3
FWIW, tôi ghét các tệp .inl. Tại sao phải chia nhỏ mã của bạn nhiều hơn mức cần thiết?
Shog 9

10
@ shog9: Để tách giao diện khỏi triển khai. Tôi đã luôn ghét tệp C # và Java vì nó rất khó đọc giao diện vì tất cả các chi tiết triển khai messey.
Martin York

8
@Martin - thật không may, C ++ cung cấp cho chúng ta một sự kết hợp tồi của cả hai thế giới - giao diện và một phần của quá trình triển khai trong tiêu đề, phần còn lại của việc triển khai trong tệp .cpp. Ngay cả khi bạn tránh các hàm nội tuyến (hoặc đặt chúng trong các tệp .inl), bạn vẫn phải làm lộn xộn giao diện với các chi tiết khó hiểu về các thành viên riêng tư trừ khi bạn có thể sử dụng thành ngữ ma cô một cách tôn giáo.
Michael Burr,

5
Vâng, tôi chưa bao giờ hiểu lập luận rằng tiêu đề tách giao diện khỏi việc triển khai. Rõ ràng là họ không. Một giao diện không nên chứa tất cả các thành viên riêng tư.
jalf

@LokiAstari: Công bằng mà nói, Java / C # có công cụ rất tốt cung cấp phác thảo giao diện tự động. Người ta có thể nói theo cách khác: Trong C ++, bạn phải giải quyết một vấn đề theo cách thủ công, điều này hoàn toàn có thể được máy tính giải quyết.
bluenote10

Câu trả lời:


139

.inlcác tệp không bao giờ là bắt buộc và không có ý nghĩa đặc biệt đối với trình biên dịch. Nó chỉ là một cách cấu trúc mã của bạn cung cấp một gợi ý cho những người có thể đọc nó.

Tôi sử dụng .inltệp trong hai trường hợp:

  • Để biết các định nghĩa về hàm nội tuyến.
  • Để biết định nghĩa về các mẫu chức năng.

Trong cả hai trường hợp, tôi đặt các khai báo của các hàm trong một tệp tiêu đề, tệp này được bao gồm bởi các tệp khác, sau đó tôi #includeđặt .inltệp ở cuối tệp tiêu đề.

Tôi thích nó vì nó tách giao diện khỏi việc triển khai và làm cho tệp tiêu đề dễ đọc hơn một chút. Nếu bạn quan tâm đến chi tiết triển khai, bạn có thể mở .inltệp và đọc. Nếu bạn không, bạn không cần phải làm thế.


2
Thật vậy, nó chủ yếu là về việc tách giao diện khỏi việc triển khai.
Pavel Minaev 30/07/09

1
Tôi cũng đã thấy .ipp và .ixx được sử dụng cho các định nghĩa nội tuyến và .tpp và .txx cho mẫu một.
AProgrammer,

1
Ví dụ, Thư viện C ++ chuẩn GNU sử dụng .tcccho các tệp triển khai mẫu.
musiphil

1
@NickMeyer glmsử dụng .hpp và .inl theo đúng như cách bạn đã đề cập ở trên.
Thật

Vì vậy, nó giống như một tiêu đề?
Aaron Franke

90

Nick Meyer đúng: Trình biên dịch không quan tâm đến phần mở rộng của tệp bạn đang đưa vào, vì vậy những thứ như ".h", ".hpp", ".hxx", ".hh", ".inl", ".inc", v.v. là một quy ước đơn giản, để làm rõ những gì các tệp được cho là chứa.

Ví dụ tốt nhất là các tệp tiêu đề STL không có phần mở rộng nào.

Thông thường, các tệp ".inl" chứa mã nội tuyến (do đó có phần mở rộng ".inl").

Các tệp ".inl" là một tệp cần thiết khi bạn có một chu kỳ phụ thuộc giữa mã tiêu đề .

Ví dụ:

// A.hpp
struct A
{
    void doSomethingElse()
    {
       // Etc.
    }

    void doSomething(B & b)
    {
       b.doSomethingElse() ;
    }
} ;

Và:

// B.hpp
struct B
{
    void doSomethingElse()
    {
       // Etc.
    }

    void doSomething(A & a)
    {
       a.doSomethingElse() ;
    }
} ;

Không có cách nào bạn sẽ phải biên dịch nó, bao gồm cả việc sử dụng khai báo chuyển tiếp.

Giải pháp sau đó là chia nhỏ định nghĩa và triển khai thành hai loại tệp tiêu đề:

  • hpp để khai báo / định nghĩa tiêu đề
  • inl để triển khai tiêu đề

Điều này được chia thành ví dụ sau:

// A.hpp

struct B ;

struct A
{
    void doSomethingElse() ;
    void doSomething(B & b) ;
} ;

Và:

// A.inl
#include <A.hpp>
#include <B.hpp>

inline void A::doSomethingElse()
{
   // Etc.
}

inline void A::doSomething(B & b)
{
   b.doSomethingElse() ;
}

Và:

// B.hpp

struct A ;

struct B
{
    void doSomethingElse() ;
    void doSomething(A & a) ;
} ;

Và:

// B.INL
#include <B.hpp>
#include <A.hpp>

inline void B::doSomethingElse()
{
   // Etc.
}

inline void B::doSomething(A & a)
{
   a.doSomethingElse() ;
}

Bằng cách này, bạn có thể đưa bất kỳ tệp ".inl" nào bạn cần vào nguồn của riêng mình và nó sẽ hoạt động.

Một lần nữa, tên hậu tố của các tệp được bao gồm không thực sự quan trọng, chỉ là công dụng của chúng.


5
Điều này giải thích lợi ích thực sự (hoặc sự cần thiết) của việc tách biệt, và lẽ ra phải được chọn làm câu trả lời.
musiphil

Nếu hàm không nội tuyến, bạn có chuẩn tệp .cpp cho phần triển khai không?
Bublafus

@Bublafus If the function were not inline, you would you standard .cpp file for the implementation part?:: Có thể. Mẫu là ví dụ về mã thường không thể ẩn trong tệp .CPP, vì vậy trong trường hợp đó, tệp .INL sẽ là bắt buộc.
paercebal

32

Vì không ai khác đã đề cập đến nó:

Việc sử dụng tệp .inl để lưu trữ các hàm nội tuyến của bạn có thể hữu ích để tăng tốc độ biên dịch.

Nếu bạn chỉ bao gồm các khai báo (.h) nơi bạn cần khai báo và chỉ bao gồm các triển khai nội tuyến (.inl) khi bạn cần chúng (nghĩa là có thể chỉ trong .cpp và các tệp .inl khác, không phải .h), nó có thể có ảnh hưởng có lợi đến phần phụ thuộc tiêu đề của bạn.

Đây có thể là một chiến thắng đáng kể đối với các dự án lớn hơn với nhiều lớp tương tác.


7
+1: thế giới chắc chắn là một nơi khác khi bạn đang quản lý hàng triệu dòng mã và hàng nghìn tệp.
gatorfax,

vì vậy bạn không bao giờ nên đưa .inl vào các tệp tiêu đề? Tôi luôn có cảm giác rằng .inl nên được đặt ở cuối tệp tiêu đề vì các hàm nội tuyến yêu cầu khai báo và triển khai để có thể truy cập cùng một lúc.
Icebone 1000

1
Icebone1000 không phải tất cả các mô-đun bao gồm tiêu đề đều nhất thiết muốn sử dụng các hàm nội tuyến, vì vậy chúng không cần đọc các triển khai, chúng không bắt buộc phải hiện diện nếu chúng không được sử dụng.
Andy J Buchanan

1
Tôi không hiểu làm thế nào nó có thể nhanh hơn, vì trình biên dịch phải thực hiện nhiều công việc hơn để bao gồm và kết hợp các đơn vị dịch.
Nikos

1
@Nikos Tôi nghĩ ý của anh ấy là nhanh hơn liên quan đến việc đưa tất cả các hàm nội tuyến vào các tệp tiêu đề của bạn.
CoffeeTableEspresso

3

Theo kinh nghiệm của tôi, các tệp .inl được sử dụng để xác định các hàm nội tuyến. Khi chúng nằm trong tệp .inl, tệp có thể được đưa vào tiêu đề để nhận các hàm nội tuyến và trong tệp .c để nhận các định nghĩa hàm thông thường.

Bằng cách này, cùng một nguồn có thể dễ dàng làm việc hơn với các trình biên dịch không có hỗ trợ chức năng nội tuyến cũng như các trình biên dịch có hỗ trợ.

Chúng thường được sử dụng với mã C thẳng, không thường xuyên với mã C ++ vì tất cả các trình biên dịch C ++ đều hỗ trợ các hàm nội tuyến.


Tôi không thấy ích lợi khi làm điều này chỉ để nhận được sự hỗ trợ của C. Đối với C, bạn chỉ cần điều kiện #define inline staticvà xác định các hàm nội tuyến của bạn trong tiêu đề.
Pavel Minaev 30/07/09

Tôi đoán điều này tránh cho nhiều bản sao của cùng một hàm kết thúc ở dạng nhị phân. Tôi chỉ nói rằng tôi đã thấy các tệp .inl được sử dụng theo cách này, không phải đó là kỹ thuật duy nhất (hoặc thậm chí tốt nhất).
Michael Burr,

1

Tôi tin rằng đó chỉ là quy ước đặt tên cho tệp "tiêu đề" bao gồm mã nội tuyến. nó để tệp .h có thể chứa các định nghĩa và tệp .inl chứa mã nội tuyến cần thiết cho các mẫu.

Tôi không tin rằng có gì khác ngoài quy ước đặt tên để làm cho mục đích của tệp rõ ràng

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.