Public trong C++: Cửa sổ tâm hồn của đối tượng!
C++

Public trong C++: Cửa sổ tâm hồn của đối tượng!

Author

Admin System

@root

Ngày xuất bản

20 Mar, 2026

Lượt xem

3 Lượt

"public"

Chào các 'dev-tuber' tương lai! Giảng viên Creyt đây, và hôm nay chúng ta sẽ 'unboxing' một từ khóa mà nhìn thì đơn giản, nhưng lại là xương sống của mọi 'deal' trong lập trình hướng đối tượng (OOP) của C++: từ khóa public.

1. public là gì và để làm gì? (Creyt's POV)

Nói nôm na thế này, bạn hình dung mỗi đối tượng (object) trong code của chúng ta như một ngôi nhà. Ngôi nhà có phòng khách, phòng ngủ, nhà bếp... và cả cái cửa chính, cửa sổ. Từ khóa public trong C++ chính là cái cửa chính và cửa sổ của ngôi nhà đó!

Khi bạn khai báo một thành viên (có thể là biến dữ liệu - data member hay hàm - member function) là public, nghĩa là bạn đang tuyên bố: "Này thế giới bên ngoài, các bạn CÓ THỂ nhìn thấy và tương tác trực tiếp với thành viên này của tôi!". Nó giống như việc bạn để cái chuông cửa hay cái hòm thư ở ngoài cổng nhà mình vậy – ai cũng có thể nhấn chuông hoặc bỏ thư vào.

Mục đích cốt lõi: public dùng để định nghĩa giao diện (interface) của một đối tượng. Nó là 'bộ mặt' mà đối tượng muốn phô bày ra cho các đối tượng khác trong chương trình sử dụng. Nhờ có public, các đối tượng có thể 'nói chuyện' với nhau, gọi các hàm của nhau, hoặc truy cập các thông tin cần thiết một cách có kiểm soát.

2. Code Ví Dụ Minh Hoạ: "Đập hộp" public

Để dễ hình dung, chúng ta hãy tạo một lớp Smartphone đơn giản nhé. Một chiếc smartphone có thể có tên, giá, và các chức năng như gọi điện, chụp ảnh.

#include <iostream>
#include <string>

// Định nghĩa lớp Smartphone
class Smartphone {
public: // Mọi thứ bên dưới đây đều là public
    // Thuộc tính (Data Members) - Dữ liệu công khai
    std::string brand;
    std::string model;
    double price;

    // Phương thức (Member Functions) - Hành vi công khai
    void makeCall(const std::string& number) {
        std::cout << "Calling " << number << " from my " << brand << " " << model << ".\n";
    }

    void takePhoto() {
        std::cout << "Taking a photo with my " << brand << " " << model << ". Click!\n";
    }

    // Constructor - Hàm khởi tạo (thường là public để tạo đối tượng)
    Smartphone(std::string b, std::string m, double p) : brand(b), model(m), price(p) {
        std::cout << "A new " << brand << " " << model << " is born!\n";
    }
};

int main() {
    // Tạo một đối tượng Smartphone
    Smartphone myPhone("Apple", "iPhone 15 Pro Max", 1200.0);

    // Truy cập các thuộc tính public trực tiếp
    std::cout << "My phone is a " << myPhone.brand << " " << myPhone.model << ", costing $ " << myPhone.price << ".\n";

    // Gọi các phương thức public
    myPhone.makeCall("0912345678");
    myPhone.takePhoto();

    // Thử thay đổi giá trị thuộc tính public
    myPhone.price = 1150.0; // Giảm giá!
    std::cout << "New price: $ " << myPhone.price << ".\n";

    return 0;
}

Trong ví dụ trên, brand, model, price, makeCall(), takePhoto()Smartphone() constructor đều là public. Điều này cho phép chúng ta từ hàm main() (bên ngoài lớp Smartphone) có thể dễ dàng truy cập và sử dụng chúng.

Illustration

3. Mẹo hay để nhớ (Best Practices) và dùng thực tế

Đây là bí kíp 'đắc địa' mà các 'lão làng' lập trình thường truyền lại, và Creyt cũng nhấn mạnh:

  • Nguyên tắc 'Giao diện công khai, triển khai riêng tư' (Public Interface, Private Implementation): Luôn cố gắng giữ các dữ liệu (thuộc tính) của lớp là private (như phòng ngủ của bạn vậy, chỉ bạn mới vào được). Chỉ những hàm nào thực sự cần thiết để đối tượng khác tương tác với đối tượng của bạn thì mới đặt là public. Ví dụ: bạn không để người lạ tự tiện vào phòng ngủ của mình, nhưng bạn sẽ mở cửa cho họ vào phòng khách để nói chuyện.
  • Hạn chế public cho dữ liệu trực tiếp: Trừ những trường hợp đặc biệt, đừng bao giờ để các biến thành viên trực tiếp là public (như brand, model, price trong ví dụ trên). Thay vào đó, hãy dùng các phương thức public để lấy (getters) hoặc đặt (setters) giá trị cho chúng. Điều này giúp bạn kiểm soát chặt chẽ dữ liệu, thêm logic kiểm tra hợp lệ nếu cần. Ví dụ, bạn có thể kiểm tra xem giá có phải là số âm không trước khi gán.
    • Ví dụ về Getters/Setters:
    class SmartphoneImproved {
    private:
        std::string brand;
        std::string model;
        double price;
    
    public:
        // Constructor
        SmartphoneImproved(std::string b, std::string m, double p) {
            setBrand(b);
            setModel(m);
            setPrice(p);
        }
    
        // Public Getters
        std::string getBrand() const { return brand; }
        std::string getModel() const { return model; }
        double getPrice() const { return price; }
    
        // Public Setters (có thể thêm logic kiểm tra)
        void setBrand(const std::string& b) { brand = b; }
        void setModel(const std::string& m) { model = m; }
        void setPrice(double p) {
            if (p >= 0) {
                price = p;
            } else {
                std::cout << "Error: Price cannot be negative!\n";
            }
        }
    
        void makeCall(const std::string& number) {
            std::cout << "Calling " << brand << " " << model << ".\n";
        }
    };
    // Trong main, bạn sẽ gọi myPhoneImproved.setPrice(-100); và thấy thông báo lỗi thay vì gán giá trị sai.
    

4. Học thuật Harvard: Khía cạnh sâu của public

Ở cấp độ 'sáng đèn' như Harvard, public không chỉ là một từ khóa mà là một trụ cột của Đóng gói (Encapsulation) – một trong bốn nguyên lý cơ bản của OOP. Đóng gói là việc nhóm dữ liệu và các phương thức thao tác với dữ liệu đó vào một đơn vị duy nhất (lớp), và kiểm soát quyền truy cập vào chúng.

  • Kiểm soát truy cập (Access Control): public là một access specifier (bộ chỉ định truy cập) cho phép bạn định rõ ranh giới giữa 'bên trong' và 'bên ngoài' của một lớp. Nó giúp duy trì tính toàn vẹn của dữ liệu và hành vi của đối tượng.
  • Tính mô-đun (Modularity): Khi bạn thiết kế các lớp với giao diện public rõ ràng, các lớp đó trở nên độc lập và dễ dàng tái sử dụng hơn. Một lớp chỉ cần biết cách tương tác với giao diện public của lớp khác, không cần quan tâm đến chi tiết triển khai bên trong (điều này gọi là Information Hiding - che giấu thông tin).
  • Tính ổn định (Stability): Bằng cách chỉ công khai những gì cần thiết, bạn có thể thay đổi cách triển khai nội bộ của một lớp (ví dụ: thay đổi thuật toán trong một phương thức private) mà không làm ảnh hưởng đến các phần khác của chương trình đang sử dụng giao diện public của lớp đó. Đây là một yếu tố cực kỳ quan trọng trong việc bảo trì và mở rộng phần mềm.

5. public trong thế giới thực: Ai đang dùng public?

Thực ra, bạn đang tương tác với public mỗi ngày mà không hay biết đấy!

  • API (Application Programming Interface): Mỗi khi bạn sử dụng một thư viện lập trình (ví dụ: std::cout để in ra màn hình, std::vector::push_back() để thêm phần tử vào vector trong C++), bạn đang gọi các phương thức public của các lớp hoặc đối tượng được cung cấp bởi thư viện đó. Các thư viện này được thiết kế để bạn chỉ cần biết cách gọi chúng, chứ không cần biết chúng hoạt động bên trong như thế nào.
  • Các hệ điều hành: Khi bạn click vào một icon trên desktop, bạn đang kích hoạt một phương thức public của một ứng dụng nào đó. Hệ điều hành cung cấp các API public để các ứng dụng có thể tương tác với phần cứng, file system, v.v.
  • Game Development: Trong một game, nhân vật của bạn (một đối tượng Player) có các phương thức public như move(), attack(), useItem(). Các đối tượng khác (kẻ thù, môi trường) sẽ gọi các phương thức này để tương tác với nhân vật của bạn.
  • Website/Ứng dụng Web: Khi bạn nhấn nút 'Thêm vào giỏ hàng' trên một trang thương mại điện tử, bạn đang kích hoạt một phương thức public (thường là một hàm trong controller hoặc service) của hệ thống backend để xử lý yêu cầu của bạn.

6. Thử nghiệm và hướng dẫn nên dùng cho case nào

Thử nghiệm 'nhẹ đô':

Hãy tưởng tượng bạn có lớp Smartphone ở trên, nhưng bạn muốn biến brand thành private.

#include <iostream>
#include <string>

class Smartphone {
private:
    std::string brand; // Giờ brand là private!
public:
    std::string model;
    double price;

    void makeCall(const std::string& number) {
        std::cout << "Calling " << number << " from my " << brand << " " << model << ".\n";
    }

    Smartphone(std::string b, std::string m, double p) : brand(b), model(m), price(p) {}
};

int main() {
    Smartphone myPhone("Apple", "iPhone 15 Pro Max", 1200.0);

    // LỖI BIÊN DỊCH! Không thể truy cập brand vì nó là private!
    // std::cout << myPhone.brand; 
    // myPhone.brand = "Samsung"; 

    myPhone.makeCall("0912345678"); // Vẫn hoạt động vì makeCall là public và có thể truy cập brand bên trong lớp.

    return 0;
}

Khi bạn thử biên dịch đoạn code này, trình biên dịch sẽ 'tố cáo' bạn ngay lập tức rằng brandprivate và không thể truy cập trực tiếp từ main(). Điều này minh họa rõ ràng sức mạnh của publicprivate trong việc kiểm soát truy cập.

Khi nào nên dùng public?

  • Cho các phương thức thể hiện hành vi chính của đối tượng: makeCall(), takePhoto(), move(), saveData(), calculateTotal()... Đây là những 'hành động' mà đối tượng của bạn có thể thực hiện và bạn muốn các đối tượng khác có thể yêu cầu nó làm.
  • Cho các constructor và destructor: Để có thể tạo và hủy đối tượng từ bên ngoài lớp.
  • Cho các phương thức getter/setter (có kiểm soát): Như getBrand(), setPrice() trong ví dụ SmartphoneImproved. Đây là cách 'an toàn' để cho phép truy cập hoặc sửa đổi dữ liệu private.
  • Trong những trường hợp cụ thể, khi bạn thực sự muốn dữ liệu được truy cập trực tiếp và không cần bất kỳ logic kiểm tra nào: Tuy nhiên, hãy cân nhắc kỹ lưỡng và thường thì bạn sẽ không thấy nhiều trường hợp như vậy trong thiết kế tốt.

Nhớ nhé các 'code-ninja', public không chỉ là một từ khóa, nó là một triết lý thiết kế! Sử dụng nó một cách khôn ngoan sẽ giúp code của bạn 'sạch sẽ', dễ bảo trì và 'ngầu' hơn rất nhiều. Hẹn gặp lại trong bài học tiếp theo!

Thuộc Series: C++

Bài giảng này được tự động xuất bản ngẫu nhiên từ thư viện kiến thức. Đừng quên đón xem các Từ khoá Hướng Dẫn tiếp theo nhé!

#tech #cyberpunk #laravel
Chỉnh sửa bài viết

Bình luận (0)

Vui lòng Đăng Nhập để Bình luận

Hỗ trợ Markdown cơ bản
Nguyễn Văn A
1 ngày trước

Tính năng này đỉnh quá ad ơi, chờ mãi mới thấy một blog Tiếng Việt có UI/UX xịn như vầy!