STARTING
CONTROL STATEMENT
FUNCTION
ARRAY & POINTER
OOP
STL
ITERATORS
OTHER FEATURES
CÁC CHỦ ĐỀ
BÀI MỚI NHẤT
MỚI CẬP NHẬT

Try, Catch, và Throw của Exception Handling trong C++

Trong quá trình phát triển phần mềm, việc xử lý các tình huống không mong muốn và lỗi là một phần quan trọng để đảm bảo tính ổn định và đáng tin cậy của ứng dụng. Trong ngôn ngữ lập trình C++, Exception Handling (xử lý ngoại lệ) là một kỹ thuật mạnh mẽ giúp quản lý và xử lý các ngoại lệ, từ các lỗi dữ liệu đầu vào không hợp lệ đến các vấn đề phức tạp trong I/O hoặc xử lý dữ liệu.

test php

banquyen png
Bài viết này được đăng tại freetuts.net, không được copy dưới mọi hình thức.

Trong bài viết này, mình sẽ tìm hiểu sâu hơn về Exception Handling trong C++. Mình sẽ tìm hiểu về cú pháp và hoạt động của Try, Catch, và Throw, các loại exception có sẵn và cách định nghĩa các loại exception tùy chỉnh. Mình cũng sẽ thảo luận về cách sử dụng Exception Handling trong các tình huống thực tế và những lưu ý cần thiết khi thực hiện.

Hãy cùng đi vào chi tiết với Exception Handling trong C++ để hiểu rõ hơn về cách nó hoạt động và cách áp dụng trong việc phát triển phần mềm.

ExceptionHandling png

Exception Handling trong C++ là gì?

Exception Handling là một kỹ thuật trong lập trình cho phép xử lý các tình huống không mong muốn và lỗi trong chương trình một cách kiểm soát. Thay vì gây ra sự cố và làm cho chương trình kết thúc không mong muốn, Exception Handling cho phép chương trình xác định và xử lý các ngoại lệ một cách cẩn thận.

Bài viết này được đăng tại [free tuts .net]

  • Exception Handling là cách tiếp cận được sử dụng trong lập trình để xử lý các vấn đề và lỗi xảy ra trong quá trình thực thi chương trình một cách kiểm soát.
  • Ý nghĩa của Exception Handling là cung cấp một cơ chế cho phép chương trình nhận diện và xử lý các tình huống ngoại lệ một cách linh hoạt, giúp tránh được việc chương trình bị crash hoặc không thể dự báo trong quá trình chạy.

Vai trò và ưu điểm của Exception Handling

Vai trò của Exception Handling là giúp chương trình duy trì tính ổn định và đáng tin cậy bằng cách xử lý các tình huống ngoại lệ một cách chính xác và dễ dàng nhất có thể.

Ưu điểm của Exception Handling bao gồm:

  • Tăng tính linh hoạt: Cho phép xử lý các tình huống ngoại lệ một cách linh hoạt, tạo điều kiện cho việc điều chỉnh và tái sử dụng mã nguồn.
  • Giảm độ phức tạp: Giúp tách biệt logic xử lý ngoại lệ khỏi logic chính của chương trình, làm cho mã nguồn trở nên dễ đọc và dễ bảo trì hơn.
  • Nâng cao tính ổn định: Loại bỏ các vấn đề không mong muốn và giữ cho chương trình tiếp tục hoạt động một cách bình thường ngay cả khi có lỗi xảy ra.

Chính vì những lợi ích mà Exception Handling mang lại, nó đã trở thành một phần quan trọng và không thể thiếu trong phát triển phần mềm hiện đại.

Cú pháp của Try, Catch, và Throw trong C++

Try

Đặt mã có thể sinh ra exception vào khối try

try {
    // Mã có thể sinh ra exception
    // Ném exception nếu có lỗi
} 

Trong khối try, mình đặt mã mà muốn giám sát để xử lý các tình huống ngoại lệ. Nếu một exception được sinh ra trong khối try, nó sẽ được ném ra và được bắt bởi một hoặc nhiều khối catch.

Catch

Xử lý exception được sinh ra trong khối try

catch (exception_type1& e) {
    // Xử lý exception_type1
}
catch (exception_type2& e) {
    // Xử lý exception_type2
}
// Bài viết được đăng tại freetuts.net
// Các khối catch khác có thể được thêm vào tùy ý

Trong một khối catch, mình xác định loại exception mà mình muốn xử lý. Nếu một exception tương ứng với loại được xác định được ném ra từ khối try, chương trình sẽ chuyển đến khối catch tương ứng để xử lý nó.

Throw

Sinh ra một exception và ném nó để bắt

throw exception_type(arguments);

Throw được sử dụng để sinh ra một exception và ném nó ra khỏi khối try hiện tại. Bạn có thể throw bất kỳ loại exception nào, kể cả các đối tượng tùy chỉnh mà mình đã định nghĩa.

Các loại Exception trong C++

Các loại Exception có sẵn trong C++

Trong C++, có một số loại exception có sẵn mà mình có thể sử dụng để xử lý các tình huống ngoại lệ thông thường. Dưới đây là một số loại exception phổ biến:

  • std::exception: Là lớp cơ sở cho tất cả các lớp exception trong STL. Nó chứa một phương thức what() để trả về một chuỗi mô tả lỗi.

  • std::runtime_error: Được sử dụng khi có một lỗi xảy ra trong thời gian chạy chương trình và không thể được xử lý một cách thông thường.

  • std::logic_error: Được sử dụng khi có lỗi trong logic của chương trình, không phải là lỗi thời gian chạy.

  • std::bad_alloc: Được ném ra khi không thể cấp phát bộ nhớ động.

Cách định nghĩa và sử dụng các loại Exception tùy chỉnh

cũng có thể định nghĩa và sử dụng các loại exception tùy chỉnh trong C++. Điều này cho phép mình xử lý các tình huống ngoại lệ cụ thể mong muốn.

#include <iostream>
#include <stdexcept>

class MyException : public std::exception {
public:
    const char* what() const noexcept override {
        return "Đã xảy ra ngoại lệ tùy chỉnh của freetuts.net";
    }
};
// Bài viết được đăng tại freetuts.net

int main() {
    try {
        throw MyException();
    } catch (const std::exception& e) {
        std::cerr << "Exception caught: " << e.what() << std::endl;
    }
    return 0;
}

Output:

Exception caught: Đã xảy ra ngoại lệ tùy chỉnh của freetuts.net

Trong ví dụ trên, mình định nghĩa một lớp tùy chỉnh MyException kế thừa từ std::exception. Cũng triển khai phương thức what() để trả về một chuỗi mô tả lỗi. Sau đó, trong hàm main, mình ném và bắt một đối tượng MyException.

Quản lý Exception trong C++

Sử dụng nhiều khối Catch để xử lý các loại Exception khác nhau

Trong một chương trình C++, có thể có nhiều loại exception khác nhau có thể được sinh ra. Để xử lý chúng một cách hiệu quả, có thể sử dụng nhiều khối catch để xử lý từng loại exception một cách riêng biệt.

try {
    // Mã có thể sinh ra exception
} catch (const std::runtime_error& e) {
    // Xử lý các runtime errors
   // Bài viết được đăng tại freetuts.net
} catch (const std::logic_error& e) {
    // Xử lý các logic errors
} catch (const std::exception& e) {
    // Xử lý các exception khác
} catch (...) {
    // Xử lý tất cả các exception không mong muốn
}

Trong ví dụ trên,mình sử dụng nhiều khối catch để xử lý các loại exception khác nhau. Khối catch cuối cùng với dấu "..." được sử dụng để xử lý tất cả các loại exception không được nắm bắt trong các khối catch trước đó.

Sử dụng khối Catch all để xử lý các Exception không mong muốn

try {
    // Mã có thể sinh ra exception
} catch (...) {
    // Xử lý tất cả các exception không mong muốn
}

Trong một số trường hợp, khi mình không biết chính xác loại exception nào có thể được sinh ra, có thể sử dụng khối catch all để xử lý tất cả các loại exception không mong muốn. Tuy nhiên, việc sử dụng khối catch all nên được hạn chế để tránh việc mặc cảm với các lỗi và gây ra các vấn đề khó khăn trong việc gỡ lỗi.

Cách sử dụng Exception Handling trong C++

Xử lý các lỗi dữ liệu đầu vào không hợp lệ

Trong các ứng dụng, đôi khi người dùng có thể cung cấp dữ liệu đầu vào không hợp lệ. Exception Handling có thể được sử dụng để xác nhận và xử lý các lỗi này một cách linh hoạt.

try {
    // Kiểm tra và xử lý dữ liệu đầu vào
    if (input < 0) {
        throw std::invalid_argument("Input must be non-negative");
    }
// Bài viết được đăng tại freetuts.net
} catch (const std::invalid_argument& e) {
    std::cerr << "Invalid argument: " << e.what() << std::endl;
}

Xử lý các lỗi liên quan đến file và I/O

Trong các ứng dụng đọc và ghi file, các lỗi I/O có thể xảy ra, như mất kết nối hoặc không thể mở file. Exception Handling có thể được sử dụng để xử lý và thông báo về các lỗi này.

try {
    // Mở file
    std::ifstream file("example.txt");
    if (!file) {
        throw std::ios_base::failure("Cannot open file");
    }
    // Đọc dữ liệu từ 
// Bài viết được đăng tại freetuts.net
} catch (const std::ios_base::failure& e) {
    std::cerr << "I/O error: " << e.what() << std::endl;
}

Xử lý các lỗi trong mạng lưới và kết nối cơ sở dữ liệu

Trong ứng dụng liên quan đến mạng hoặc cơ sở dữ liệu, việc xử lý các lỗi kết nối là quan trọng. Exception Handling có thể được sử dụng để xử lý các ngoại lệ phát sinh từ việc kết nối.

try {
    // Kết nối đến cơ sở dữ liệu
    if (!connectToDatabase()) {
        throw std::runtime_error("Failed to connect to database");
    }
// Bài viết được đăng tại freetuts.net
    // Thực hiện các thao tác trên cơ sở dữ liệu
} catch (const std::runtime_error& e) {
    std::cerr << "Database error: " << e.what() << std::endl;
}

Trong mỗi tình huống, việc sử dụng Exception Handling giúp xác định và xử lý các lỗi một cách dễ dàng và linh hoạt.

Ví dụ Exception Handling trong C++

Ví dụ về việc sử dụng Try, Catch, và Throw trong một chương trình đơn giản:

#include <iostream>

void processNumber(int num) {
    try {
        if (num == 0) {
            throw "Invalid number: cannot be zero";
        }
        std::cout << "Result: " << 10 / num << std::endl;
    } catch (const char* msg) {
        std::cerr << "Exception caught: " << msg << std::endl;
    }
}
// Bài viết được đăng tại freetuts.net

int main() {
    processNumber(5);   // Valid number
    processNumber(0);   // Invalid number
    return 0;
}

Output:

Screenshot 202024 04 06 20111501 1  png

Ví dụ về cách xử lý Exception trong các tình huống thực tế:

#include <iostream>
#include <fstream>

void processFile(const std::string& filename) {
    try {
        std::ifstream file(filename);
        if (!file.is_open()) {
            throw std::runtime_error("Failed to open file: " + filename);
        }
        // Process file contents
    } catch (const std::exception& e) {
        std::cerr << "Exception caught: " << e.what() << std::endl;
    }
}
// Bài viết được đăng tại freetuts.net
int main() {
    processFile("input.txt");   // Valid file
    processFile("nonexistent.txt");   // Invalid file
    return 0;
}

Output:

Screenshot 202024 04 06 20111430 png

Trong ví dụ A, chương trình thực hiện phép chia 10 cho số được truyền vào hàm processNumber. Nếu số đó là 0, ngoại lệ sẽ được ném và được bắt bởi khối catch, hiển thị thông báo lỗi.

Trong ví dụ B, chương trình mở một file và xử lý nội dung của nó. Nếu không thể mở file, ngoại lệ sẽ được ném và thông điệp lỗi sẽ được hiển thị.

Kết bài

Trong bài viết này, mình đã tìm hiểu về Exception Handling trong C++, một cơ chế quan trọng để xử lý các tình huống ngoại lệ trong quá trình chạy chương trình. Và đã đi qua các khái niệm cơ bản như Try, Catch và Throw, cùng với cách sử dụng và quản lý các loại Exception.

Mình cũng đã thảo luận về việc sử dụng Exception Handling trong các tình huống thực tế, từ xử lý lỗi dữ liệu không hợp lệ đến xử lý lỗi liên quan đến file và I/O. Cuối cùng,đã xem xét một số lưu ý và thực hành tốt khi sử dụng Exception Handling, cũng như cung cấp ví dụ minh họa cụ thể để làm rõ các khái niệm đã học.

Việc hiểu và sử dụng Exception Handling một cách hiệu quả là một phần quan trọng của việc phát triển phần mềm ổn định và tin cậy trong ngôn ngữ lập trình C++.

Cùng chuyên mục:

Các hàm xử lý ngày tháng (datetime.h) trong C/C++

Các hàm xử lý ngày tháng (datetime.h) trong C/C++

Các hàm xử lý số thực (float.h) trong C/C++

Các hàm xử lý số thực (float.h) trong C/C++

Các hàm xử lý số nguyên lớn (bigint.h) trong C/C++

Các hàm xử lý số nguyên lớn (bigint.h) trong C/C++

Các hàm xử lý thời gian (time.h) trong C

Các hàm xử lý thời gian (time.h) trong C

Các hàm xử lý chuỗi (string.h) trong C/C++

Các hàm xử lý chuỗi (string.h) trong C/C++

Thread Pools và Parallel Algorithms trong C++

Thread Pools và Parallel Algorithms trong C++

Tạo và quản lý các Multithreading trong C++

Tạo và quản lý các Multithreading trong C++

Xử lý ngoại lệ khi làm việc với Memory Allocation trong C++

Xử lý ngoại lệ khi làm việc với Memory Allocation trong C++

Cách sử dụng Lambda Expressions trong C++

Cách sử dụng Lambda Expressions trong C++

Sử dụng weak_ptr trong C++

Sử dụng weak_ptr trong C++

Sử dụng shared_ptr trong C++

Sử dụng shared_ptr trong C++

Sử dụng unique_ptr trong C++

Sử dụng unique_ptr trong C++

Tổng quan về Smart Pointers trong C++

Tổng quan về Smart Pointers trong C++

Sử dụng Iterators trong STL của C++

Sử dụng Iterators trong STL của C++

[Iterator] Sử dụng Vector trong C++

[Iterator] Sử dụng Vector trong C++

[Iterator] Sử dụng trong List trong C++

[Iterator] Sử dụng trong List trong C++

[STL] Sử dụng Vector trong C++

[STL] Sử dụng Vector trong C++

Tổng quan về Iterators trong C++

Tổng quan về Iterators trong C++

[STL] Các hàm thường dùng của lớp Vector trong C++

[STL] Các hàm thường dùng của lớp Vector trong C++

[STL] Các hàm thông dụng của Map trong C++

[STL] Các hàm thông dụng của Map trong C++

Top