C++ Programming – Classes and class members


C++ cung cấp một số kiểu dữ liệu (data types) như là char, int, long, float, double,… để có thể giải quyết các vấn đề tương đối đơn giản; tuy nhiên rất là khó để giải quyết các vấn đề phức tạp với các kiểu dữ liệu đó. Một trong những tính năng hữu ích của C++ là định nghĩa kiểu dữ liệu của riêng bạn để có thể tương ứng với bài toán phức tạp mà bạn đang giải. Có thể bạn đã biết về enum, struct, union có khả năng được dùng để tạo ra kiểu dữ liệu tùy chỉnh của riêng bạn.
Dưới đây là ví dụ về struct được dùng để giữ giá trị về ngày tháng năm:

struct DateStruct
{
    int year;
    int month;
    int day;
};

Kiểu enum và struct đại diện cho ngôn ngữ lập trình phi hướng đối tượng truyền thống (non-object-oriented programming), thứ ngôn ngữ mà chỉ giữ dữ liệu bên trong. Trong C++ 11, chúng ta có thể khởi tạo struct như sau:

DateStruct today { 2020, 10, 14 };

Và bây giờ nếu chúng ta muốn in giá trị ngày tháng lên màn hình (thứ mà chúng ta thường làm), chỉ có thể làm được nếu chúng ta làm như sau:

#include <iostream>
 
struct DateStruct
{
    int year;
    int month;
    int day;
};
 
void print(DateStruct &date)
{
    std::cout << date.year << "/" << date.month << "/" << date.day;
}
 
int main()
{
    DateStruct today { 2020, 10, 14 }; // use uniform initialization
 
    today.day = 16; // use member selection operator to select a member of the struct
    print(today);
 
    return 0;
}

Chương trình sẽ in ra :
2020/10/16


Classes

Trong thế giới của các ngôn ngữ lập trình hướng đối tượng, chúng ta thường muốn kiểu dữ liệu không chỉ giữ dữ liệu, mà còn có thể cung cấp hàm để làm việc với các dữ liệu. Trong C++, chuyện này “quá là điều bình thường luôn” thông qua từ khóa class . Sử dụng từ khóa class để định nghĩa một kiểu dữ liệu của riêng người dùng, tiếng Việt gọi là Lớp.
Trong C++, class thì khá giống với struct, ngoại trừ việc class mạnh mẽ và uyển chuyển hơn. Thực tế, hãy xem đoạn code dưới, struct và class có hiệu lực như nhau:

struct DateStruct
{
    int year;
    int month;
    int day;
};
 
class DateClass
{
public:
    int m_year;
    int m_month;
    int m_day;
};

Chú ý rằng thứ duy nhất khác biệt đáng kể là từ khóa public trong class. Chúng ta sẽ bàn về nó trong các phần tiếp theo.
Giống y chang như struct, để sử dụng class, một biến của kiểu class đó phải được khai báo:

DateClass today { 2020, 10, 14 };

Trong C++, khi định nghĩa một biến của một class, chúng ta gọi đó là instantiating, biến đó là instance (mình không biết nên dịch khúc này như thế nào cả). Một biến của kiểu class đó cũng được gọi là object (khái niệm này sẽ được dùng nhiều hơn).


Member functions

Ngoài việc giữ dữ liệu, class còn cung cung cấp function (hàm). Hàm được định nghĩa bên trong class được gọi là member function hay method (hàm thành viên).
Hàm thành viên có thể được định nghĩa bên trong hoặc bên ngoài của định nghĩa class. Chúng ta sẽ định nghĩa hàm thành viên bên trong class để đơn giản cho các bạn hiểu, cách định nghĩa bên ngoài class thì chúng tôi sẽ cung cấp trong các phần tiếp theo.
Dưới đây sẽ là class Date với hàm thành viên print để in ra giá trị ngày tháng năm:

class DateClass
{
public:
    int m_year;
    int m_month;
    int m_day;
 
    void print() // defines a member function named print()
    {
        std::cout << m_year << "/" << m_month << "/" << m_day;
    }
};

Giống như các thành viên của struct, thành viên của class (bao gồm cả biến và hàm) có thể được truy cập thông qua dấu ( . )

#include <iostream>
 
class DateClass
{
public:
    int m_year;
    int m_month;
    int m_day;
 
    void print()
    {
        std::cout << m_year << "/" << m_month << "/" << m_day;
    }
};
 
int main()
{
    DateClass today { 2020, 10, 14 };
 
    today.m_day = 16; // use member selection operator to select a member variable of the class
    today.print(); // use member selection operator to call a member function of the class
 
    return 0;
}

Đây là kết quả:
2020/10/16
Chú ý rằng ví dụ về class này có chức năng tương tự như struct đã đề cập ở trên.
Tuy nhiên vẫn có một vài điểm khác biệt. Trong DateStruct, chúng ta phải truyền nó vào hàm print() như là một parameter (tham số). Mặt khác, print() không biết chúng ta muốn sử dụng DateStruct. Chỉ sau khi chúng ta sau đó truyền vào reference (tham chiếu) tới DateStruct thì nó mới hiểu.
Còn ở DateClass, chúng ta sẽ gọi “today.print()”, có nghĩa là chúng ta đang nói cho compiler (trình biên dịch) để nó gọi hàm thành viên print(), hàm mà liên kết với object today.
Và bây giờ các bạn hãy nhìn lại vào hàm thành viên print():

void print() // defines a member function named print()
    {
        std::cout << m_year << "/" << m_month << "/" << m_day;
    }

Chính xác thì m_year, m_month, m_day sẽ tham chiếu tới đâu?
Chúng tham chiếu tới object đang liên kết. Vì vậy khi chúng ta gọi “today.print()”, trình biên dịch sẽ dịch m_day là today.m_day, m_month là today.m_month, m_year là today.m_year. Nếu giả sử có một object khác là “tomorrow” cũng cùng kiểu DateClass thì khi gọi “tomorrow.print()”, m_day sẽ tham chiếu tới tomorrow.m_day.
Với các hàm không phải là hàm thành viên, chúng ta phải truyền dữ liệu vào hàm để hàm có thể làm việc. Còn với hàm thành viên, chúng ta có thể ngầm hiểu là luôn luôn có một object đi cùng để hàm đó làm việc.
Sau đây là một số luật bất thành văn mà chúng ta nên tuân theo để code rõ ràng và tiện lợi:
Hãy sử dụng tiền tố “m_” cho biến thành viên của class để phân biệt với tham số hoặc biến cục bộ bên trong hàm thành viên. Nó hữu dụng vì một số lý do sau. Một là khi chúng ta làm việc với một biến có tiền tố “m_”, chúng ta biết rằng trạng thái của class đang được thay đổi. Thứ hai, không giống như tham số hoặc biến cục bộ của hàm được khai báo trong hàm, biến với tiền tố “m_” sẽ được khai báo trong class. Vì vậy mà khi gặp biến với tiền tố “m_” thì chúng ta biết rằng chúng ta nên nhìn lên class thay vì trong hàm.
Nên định nghĩa tên class với ký tự in hoa (Capital letter).


Một chú ý về Struct trong C++

Trong ngôn ngữ C, struct chỉ có thể giữ dữ liệu, không có hàm thành viên. Trong C++, sau khi thiết kế class, Bjarne Stroustrup – tác giả của C++, đã dành rất nhiều thời gian để suy nghĩ xem có nên để struct có khả năng với class. Sau một thời gian suy xét thì câu trả lời là CÓ. Vì vậy mà mặc dù chúng tôi sử dụng từ khóa class, nhưng bạn cũng có thể dùng từ khóa struct thay thế.
Rất nhiều lập trình viên cảm thấy đây là một quyết định rất sai lầm của Bjarne; nó có thể dẫn tới nhiều nguy hiểm về bộ nhớ. Vì vậy mà thêm một điều luật bất thành văn trong C++, Struct chỉ nên giữ dữ liệu, không có hàm; còn Class thì có thể có cả hai.


Tổng kết

Class trong C++ cung cấp cho chúng ta tùy chỉnh kiểu của riêng chúng ta, có thể có cả biến và hàm. Class là một định nghĩa cơ bản của lập trình hướng đối tượng.
Hy vọng sau bài viết này, các bạn đã hiểu rõ về Class, cánh cửa để bước vào lập trình hướng đối tượng.

Nguồn tham khảo từ link:
http://www.learncpp.com/

Tác giả: Boong Gà

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s