Tách code C++ thành các file.h và file.cpp? Chắc hẳn các bạn đã từng nghe qua. Trước tới giờ, chúng ta thường chỉ viết các đoạn code ngắn, hàm đơn giản hay chỉ là một chương trình nhỏ nên chỉ cần viết 1 file.cpp là đủ. Nhưng khi xây dựng một chương trình lớn thì có nên làm như vậy?
Nếu bạn đọc đang có nhu cầu học lập trình hướng đối tượng C++, hãy tham khảo ngay series Lập trình hướng đối tượng với C++ của LTKK nhé.
Tại sao phải tách file?
Khi lưu toàn bộ code vào một file main sẽ gây ra rất nhiều vấn đề bất lợi, có thể kể đến như: Chương trình trở nên quá dài; khó quản lý, sử dụng. Giả sử ta khi muốn tìm một hàm nào đấy để chỉnh sửa thì sẽ làm tiêu tốn thời gian vì có quá nhiều hàm và không biết nó ở đâu.
Việc tách code C++ cũng như tách code ở các ngôn ngữ khác sẽ giúp:
- Dễ quản lí, bảo trì source code.
- Giúp code dễ đọc, dễ hiểu và dễ sử dụng.
- Tái sử dụng các hàm đã viết.
Tách code C++ như thế nào?
Hãy cùng xem xét ví dụ sau:
File: main.cpp
#include <iostream> #include <string> #include <cmath> using namespace std; // Các hàm tính toán - Math int UCLN(int a, int b){ if(a == b) return a; else if(a > b) return UCLN(a - b, b); else return UCLN(a, b - a); } int BCNN(int a, int b){ int uc = UCLN(a, b); return a * b / uc; } bool laSoNguyenTo(int n){ if(n < 2) return false; else if(n == 2) return true; else{ int num = sqrt(n); for(int i = 2; i <= num; i++){ if(n % i == 0) return false; } return true; } } // Các hàm về chuỗi - string string inHoa(string xau){ for(int i = 0; i < xau.size(); i++){ if(xau[i] >= 'a' && xau[i] <= 'z') xau[i] = xau[i] - 'a' + 'A'; } return xau; } string inThuong(string xau){ for(int i = 0; i < xau.size(); i++){ if(xau[i] >= 'A' && xau[i] <= 'Z') xau[i] = xau[i] - 'A' + 'a'; } return xau; } int main(){ cout << UCLN(18, 27) << endl; cout << inHoa("Lap Trinh Khong Kho") << endl; return 0; }
Có thể thấy: Chương trình được viết vào một file main.cpp duy nhất. Và các hàm (function) của mình có 2 loại. “Loại 1: Các hàm về tính toán” và “Loại 2: Các hàm về xâu chuỗi”. Mình sẽ tách chương trình trên thành các file sau:
- Header.h – Các thư viện dùng chung như “iostream”,…
- Math_Fn.h và Math_Fn.cpp – Các hàm về tính toán
- String_Fn.h và String_Fn.cpp – Các hàm về xâu, chuỗi
- main.cpp – Hàm main, chạy code
Lưu ý:
- Việc đặt tên các file .h và .cpp trùng nhau chỉ để dễ sử dụng.
- file .h dùng để khai báo hàm và file .cpp dùng để viết hàm.
- Có thể tách file thành các cách khác nhau, đây chỉ là một ví dụ nhỏ.
Mã code các file
Một chút về file Header (.h): Bạn có thể tưởng tượng đây là một file thư viện mà mình tự viết ra. Nó chứa các khai báo hàm, định nghĩa marco và có thể chia sẽ sang các file khác. (Trong các trình biên dịch sẽ có các thư viện – file Header được nhà sản xuất viết sẵn như string.h, time.h, math.h, …)
Note: Mỗi file .h đều phải có dòng code “#pragma once” ở đầu.
a) File: Header.h
Đối với mình, đây sẽ là file include các thư viện mà tất cả các file khác đều phải có. Phổ biến nhất là <iostream>. Nhằm mục đích tái sử dụng, không cần include một thư viện nhiều lần. Ngoài ra có thể khai báo các các class, struct cần thiết vào. Thậm chí là cả using namespace std
File: Header.h
#pragma once #include <iostream> using namespace std;
b) File: Math_Fn.h và Math_Fn.cpp
File: Math_Fn.h
#pragma once #include "Header.h" #include <cmath> // Các hàm về tính toán - Math int UCLN(int a, int b); int BCNN(int a, int b); bool laSoNguyenTo(int n);
Mình đã include file Header.h nên trong file này sẽ có luôn thư viện <iostream> và cả using namespace std. Tiếp theo, chỉ cần thêm các thư viện cần thiết (cmath) và khai báo các hàm tính toán.
File: Math_Fn.cpp
#include "Math_Fn.h" int UCLN(int a, int b) { if (a == b) return a; else if (a > b) return UCLN(a - b, b); else return UCLN(a, b - a); } int BCNN(int a, int b) { int uc = UCLN(a, b); return a * b / uc; } bool laSoNguyenTo(int n) { if (n < 2) return false; else if (n == 2) return true; else { int num = sqrt(n); for (int i = 2; i <= num; i++) { if (n % i == 0) return false; } return true; } }
Ở file .cpp, mình chỉ cần include file “Math_Fn.h” và viết các hàm đã khai báo trước đó.
c) File: String_Fn.h và String_Fn.cpp
Hoàn toàn tương tự với Math_Fn. Đây sẽ là file lưu các hàm về xâu, chuỗi.
File: String_Fn.h
#pragma once #include "Header.h" #include <string> // Các hàm về chuỗi - string string inHoa(string xau); string inThuong(string xau);
File: String_Fn.cpp
#include "String_Fn.h" // Các hàm về chuỗi - string string inHoa(string xau) { for (int i = 0; i < xau.size(); i++) { if (xau[i] >= 'a' && xau[i] <= 'z') xau[i] = xau[i] - 'a' + 'A'; } return xau; } string inThuong(string xau) { for (int i = 0; i < xau.size(); i++) { if (xau[i] >= 'A' && xau[i] <= 'Z') xau[i] = xau[i] - 'A' + 'a'; } return xau; }
d) File: main.cpp
Include tất cả các file .h (header) đã viết vào, rồi viết hàm main.
File: main.cpp
// include các file header đã viết vào #include "Header.h" #include "Math_Fn.h" #include "String_Fn.h" int main() { cout << UCLN(18, 27) << endl; cout << inHoa("Lap Trinh Khong Kho") << endl; return 0; }
9 LAP TRINH KHONG KHO
Tách code C++ trong Visual Studio
Hiện nay Visual Studio đang có rất nhiều phiên bản như 2012, 2017, 2019. Trong bài này mình sẽ sử dụng phiên bản mới nhất hiện tại – Visual Studio 2022. Việc tách file sẽ không có sự khác biệt giữa các phiên bản nên các bạn đừng lo lắng nhé! Hướng dẫn dưới đây sẽ chỉ bạn từng bước cách tách code C++ trên Visual Studio.
B1: Tạo một project mới (Create a new project) rồi chọn Empty Project C++
B2: Các bạn để ý ở góc phải – Solution Expoerer sẽ có:
- Header Files: Folder lưu các file Header (.h)
- Source Files: Folder lưu các file code (.cpp)
B3: Click chuột phải vào folder muốn thêm file => Chọn Add => New Item…
B4: Chọn file phù hợp
- C++ file đối với folder “Source Files”
- Header file đối với foder “Header Files”
- Đặt tên rồi chọn Add
Và đây là kết quả: Nội dung từng file thì mình đã đề cập ở phần 3
Tách code C++ trong Visual Studio Code
Đây là một editor do Microsoft phát triển dưới dạng mã nguồn mở (opensourse) khá xịn xò được rất nhiều lập trình viên yêu thích. Hiện tại VS Code là Editor được sử dụng phổ biến nhất.
Hãy đảm bảo bạn đã cài đặt “Code Runner” và đã chạy được bằng Terminal ngay trên Visual Studio Code nhé! Hướng dẫn dưới đây sẽ chỉ bạn từng bước cách tách code C++ trên Visual Studio Code.
Tham khảo thêm: Hướng dẫn cài đặt VS Code học C++
Bước 1: Tạo một folder và lưu toàn bộ các file vào trong đó – bao gồm cả file .h và file .cpp
Bước 2: Vào Settings => Tìm kiếm “run code”
Bước 3: Ở Extension => Chọn Run Code con… (23) => Tìm kiếm Code-runner: Executor Map => Chọn Edit in settings.json
Bước 4: Ở mục cpp: Các bạn sửa $fileName thành *.cpp
Bước 5: Lưu lại và quay trở lại file main.cpp để chạy code. Khi bạn đã làm qua một lần rồi thì lần tiếp theo chỉ cần làm 2 bước: B1 và B5 thôi nhé !!! Và đây là kết quả:
Câu hỏi thường gặp (FAQ)
Dưới đây là các câu hỏi thường gặp liên quan tới vấn đề tách code C++ thành file .h và .cpp do mình tổng hợp.
Việc đổi tên thành *.cpp sẽ thay đổi những gì?
Hãy để ý ở Visual Studio, tất cả các file (.h và .cpp) sẽ đều được lưu chung vào trong một folder. Việc đổi từ $fileName sang *.cpp cũng tương tự vậy. Tức là toàn bộ các file trong cùng một project phải lưu cùng một folder thì mới chạy được trên Visual Studio Code. Nói cách khác, các file không liên quan với nhau mà để chung một folder thì khi chạy sẽ lỗi.
Khi mới bắt đầu nên tách file như thế nào?
Ở phía trên, mình đưa ra một ví dụ khá tổng quát. Tuy nhiên, khi mới bắt đầu tập tành tách file thì các bạn chỉ nên tách file thành 2 file:
- file .h: include tất cả các thư viện, using name space, khai báo tất cả các hàm
- file .h: include file .h, viết các hàm và viết hàm main.
Rồi sau đó các bạn hãy từ từ nâng số file lên – 3 file, 4 file và cuối cùng là tách file theo chức năng từng file để dễ quản lí, sử dụng nhé.
Tại sao phải khai báo hàm?
Giả sử bạn có hai hàm: function1 và fuction2. Khi ở trong function2 thì bạn có thể sử dụng function1 nếu muốn. Nhưng khi ở fuction1 thì bạn không thể dùng function2. Bởi vì trình biên dịch sẽ chạy từ trên xuống dưới, khi chưa chạy xong function1 thì function2 không tồn tại để sử dụng.
Việc khai báo hàm sẽ giúp chúng ta khắc phục điều đó. Các bạn có thể sử dụng các hàm một cách thoải mái mà không cần lo lắng đến thứ tự.
Viết hàm trong file header (.h) luôn được không?
Được, nhưng không nên. Vốn dĩ file .h sinh ra là để khai báo (thư viện, using name, class, struct, hàm – function,…). Còn việc lưu code thuộc về các source file .cpp. Do đó khi các bạn viết hàm trong file .h luôn thì thỉnh thoảng chương trình sẽ chạy sai hoặc không chạy được.
Tại sao phải có “#pragma once” ở đầu file.h?
Khi bạn include một file header (.h) thì tức là bạn đã include “toàn bộ những gì mà file header đó include”. Hãy nhìn hình dưới đây:
Như vậy ở file main.cpp, ta đã include iostream 2 lần. Điều này sẽ gây ra xung đột và có thể khiến chương trình không thể chạy được. Và thêm “#pragma once” ở đầu giúp chúng ta khắc phục điều đó, nó mang ý nghĩa include thư viện một lần, tránh sự trùng lặp.
Bản MinGW mà mình đang dùng?
MinGW là một phần mềm mã nguồn mở, một trình biên dịch ngôn ngữ C/C++ rất phổ biến trên Windows. Đối với Visual Studio thì có sẵn trình biên dịch nhưng các editor như VSCode, sublime text,… thì không. Do đó bạn phải cài thêm mới chạy code được.
Hiện tại mình đang sử dụng phiên bản MinGW mới nhất 9.2.0. Các bạn có thể download tại MinGW và cách cài đặt MinGW tại Hướng dẫn cài đặt MinGW.
Lời cảm ơn
Cảm ơn các bạn đã đọc bài viết hướng dẫn tách code C++ của mình, nếu thấy hay thì hãy chia sẽ để ủng hộ LTKK nhé! Và nếu bạn có câu hỏi hay thắc mắc gì thì hãy để lại bình luận nhé, hoặc có thể đưa lên group Lập Trình Không Khó để mọi người cùng thảo luận. Mình sẽ cố gắng update câu trả lời sớm nhất có thể.
Cảm ơn các bạn rất nhiều!!!!!
Để lại một bình luận