[Học OOP] Bài 3: Lớp trong lập trình hướng đối tượng – Kiến Thức 24h

Bài viết này sẽ đi thằng vào việc khai báo class như thế nào và một số điều cơ bản về class trong c++ hay lớp trong lập trình hướng đối tượng.

1. Lớp trong c++ là gì?

Lớp trong C++ thực chất là một kiểu dữ liệu do người lập trình quy định

Lớp trong c++ được khai báo bằng từ khóa class

Lớp trong c++ bao gồm các dữ liệu (thuộc tính) và hàm thành phần (phương thức của lớp).

2. Cú pháp khai báo lớp

Gần giống như struct trong c++, class trong c++ được khai báo theo cấu trúc như sau

1

2

3

4

5

class

<

t

ê

n

l

p

>

{

    

//thuoc tinh cua lop

    

//phuong thuc cua lop

}

Oke, bây giờ mình sẽ cụ thể hơn về cách khai báo class trong c++

1

2

3

4

5

6

7

8

9

10

11

class

<

t

ê

n

l

p

>

{

    

private

:

        

<

khai

b

á

o

d

li

u

/

h

à

m

cho

ri

ê

ng

đố

i

t

ượ

ng

>

    

protected

:

        

<

khai

b

á

o

d

li

u

/

h

à

m

cho

ri

ê

ng

đố

i

t

ượ

ng

,

            

c

ó

th

truy

c

p

t

l

p

d

n

xu

t

>

    

public

:

        

<

khai

b

á

o

d

li

u

/

h

à

m

cho

đố

i

t

ượ

ng

,

        

nh

ư

ng

truy

c

p

đượ

c

m

i

n

ơ

i

>

}

;

a. Public, protected, và private là gì?

Trong c++ chúng ta có 3 thuộc tính là Public, protected, và private. Trong mỗi thuôc tính này chúng ta hoàn toàn có thể khai báo dữ liệu của class và các hàm thành phần của nó.

Tuy nhiên với 1 trong 3 loại thuộc tính trên sẽ có vai trò và cách dùng khác nhau. Cụ thể

Private trong class như thế nào?

– Tất cả biến dữ liệu, hàm thành phần của class được khai báo trong Private chỉ được gọi và sử dụng trong phạm vi class.

– Bên ngoài class (Như hàm main, class khác,…) sẽ không truy cập bao gồm xem hay tác động dữ liệu.

Protected trong class như thế nào?

– Gần giống với Private, Thì protected cũng không cho phép bên ngoài truy cập.

– Tuy nhiên, Protected cho phép lớp dẫn xuất của nó truy cập đến các nội dung của lớp này.

– Lớp dẫn xuất là lớp được kế thừa từ lớp đó và bổ sung thêm 1 số dữ liệu, hàm, hay có mục đích khác. Về lớp dẫn xuất sẽ có bài viết khác để nói về nó.

Public trong class như thế nào?

– Trái ngược với Private và Protected, thì Public là thành phần công khai.

– Tất cả biến dữ liệu, hàm thành phần của class được khai báo trong public, sẽ được gọi và dùng ở mọi nơi.

b. Sử dụng thuộc tính như thế nào?

Việc sử dụng các thuộc tính như Public, protected, và private cũng có ý đồ riêng. Chúng ta cần đóng gói dữ liệu, một cách hiệu quả, đủ dùng, để không cho các thành phần không liên quan truy xuất hàm hoặc dữ liệu. Điều này giúp cho chương trình chúng ta đảm bảo tính đóng gói, che giấu thông tin.

Như vậy, trước mắt trong bài viết này, bạn cần nắm được phần nào bạn cho người dùng sử dụng thì khai báo public, phần nào người dùng không cần quan tâm, thì khai báo private.

c. Cú pháp khai báo thuộc tính

Theo dõi ví dụ sau đây

1

2

3

4

5

6

7

8

9

class

Rectangle

{

    

private

:

        

int

width

;

        

int

length

;

    

public

:

        

void

set

(

int

w

,

int

l

)

;

        

int

area

(

)

;

}

;

– Cú pháp khá đơn giản ví dụ như trên, ở trên mình khai báo một class quản lí hình chữ nhật, gồm chiều rộng và chiều dài, vì mình không muốn người dùng sử dụng 2 biến width, length nên để nó ở private.

– Lúc này, mình tạo thêm hàm set(w,l) để thiết lập kích thước cho hình chữ nhật này, và một hàm tính diện tích. Như vậy lúc này mình muốn người dùng khai thác, và nhập thông tin cho đối tượng này thông qua 2 hàm trên. Nên 2 hàm này sẽ ở Public.

d. Viết code cho hàm thành phần

Nếu ở mục d chỉ là khai báo các thông tin cho class thì mình sẽ cần viết code cho các hàm thành phần của nó.

Cách viết đầu tiên bạn có thể viết trực tiếp trong phần khai báo như sau:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

class

Rectangle

{

    

private

:

        

int

width

;

        

int

length

;

    

public

:

        

void

set

(

int

w

,

int

l

)

        

{

            

width

=

w

;

  

            

length

=

l

;

            

// ở trong phạm vi class, sử dụng thuộc tính dữ liệu của

            

// nó bằng cách gọi đúng tên bạn đã khai báo.

        

}

        

int

area

(

)

        

{

            

return

width*

length

;

        

}

}

;

Cách viết thứ 2 dùng để chia code thành nhiều tệp, thường bắt buộc đối với các môn học trên trường.

Trước tiên một class Rectangle chúng ta sẽ có 2 file là Rectangle.h (chứa phần khai báo như mục c) và Rectangle.cpp chứa code của các hàm thành phần.

Bây giờ mình sẽ viết nội dung cho file Rectangle.cpp

1

2

3

4

5

6

7

8

9

10

void

Rectangle

::

set

(

int

w

,

int

l

)

{

    

width

=

w

;

    

length

=

l

;

}

 

int

Rectangle

::

area

(

)

{

    

return

width*

length

;

}

 

Trong code trên có cú pháp <tên class>::<Tên hàm>

:: được gọi là phạm vi truy xuất. Chúng ta dùng nó để truy cập các dữ liệu hoặc hàm bên trong của một class cụ thể.

Trong trường hợp tách file như trên, bắt buộc bạn phải dùng phạm vi truy xuất để trình biên dịch phân biệt được đâu là hàm của class và đâu là hàm toàn cục (tức là hàm của chương trình chính).

Đây là cách tạo nhanh Class được chia file trong Visual Studio c++

Cách tạo class chia file trong Visual Studio C++Cách tạo class chia file trong Visual Studio C++Cách tạo class chia file trong Visual Studio C++

Sau khi thực hiện các bước như trên thì bạn sẽ nhận được 2 file ban đầu như thế này

Cách tạo class chia file trong Visual Studio C++

Vậy câu hỏi đặt ra lúc này là Rectangle() và ~Rectangle() trong đó là gì? Lúc này bạn phải đọc thêm phần tiếp theo bên dưới.

3. Phương thức thiết lập – Constructor

– Phương thức thiết lập hay còn gọi là constructor, là một loại phương thức đặc biệt dùng để khởi tạo thể hiện của lớp.

– Phương thức này được chạy khi chúng ta khởi tạo đối tượng, với các đối số phù hợp với các đối số được khai báo của constructor

– Constructor phải nằm ở thuộc tính public.

Trong ví dụ trên Rectangle() là constructor không có tham số. Đây là constructor mặc định, khi bạn khởi tạo đối tượng mà không truyền đối số thì Constructor mặc định sẽ được gọi. Để khai báo constructor có tham số bắt buộc phải có constructor mặc định.

Ví dụ

1

2

3

4

5

Rectangle

(

)

{

    

width

=

1

;

    

length

=

1

;

}

Điều đó có nghĩa là, nếu mình khởi tạo biến mà không có đối số thì mặc định hình chữ nhật này được set dài = 1, rộng = 1.

Vậy bây giờ mình sẽ code cho trường hợp hàm khởi tạo có đối số

1

2

3

4

5

Rectangle

(

int

w

,

int

l

)

{

    

width

=

w

;

    

length

=

l

;

}

làm thế nào để khai báo có đối số, sẽ là câu hỏi của bạn đang đặt ra trong đầu có đúng không?

ví dụ bạn khai báo Rectangle hcn1; hoặc  Rectangle hcn1();  hay  Rectangle *hcn1 = new Rectangle;

Đây là kiểu khai báo không có đối số. lúc này hàm constructor mặc định sẽ chạy, và tất nhiên dữ liệu của nó là hình chữ nhất có kích thước 1×1 như đã code bên trên.

Oke, vậy khai báo có tham số là

1

2

3

Rectangle

hcn1

(

10

,

20

)

;

Rectangle

hcn1

(

10

,

20

)

;

Rectangle *

hcn1

=

new

Rectangle

(

10

,

20

)

;

Các trường hợp này sẽ chạy vào constructor 2 tham số, và gán dữ liệu thành hình chữ nhật 10×20.

4. Phương thức hủy bỏ – Destructor

– Phương thức hủy bỏ hay còn gọi là destructor, được gọi ngay trước khi một đối tượng bị thu hồi.
– Destructor thường được dùng để thực hiện việc dọn dẹp cần thiết trước khi một đối tượng bị hủy.

Nó thường dùng trong các class có sử dụng con trỏ, cấp phát động và lúc này Destructor sẽ thu hồi bộ nhớ sau khi không dùng dữ liệu nữa.

Khai báo Destructor rất đơn giản. Ví dụ

1

2

3

~

Rectangle

(

)

{

// code

}

Lưu ý: chỉ có 1 Destructor trong class.

5. Sử dụng kiểu dữ liệu Class như thế nào?

Để sử dụng class, trước tiên bạn khai báo biến với kiểu dữ liệu class mà bạn đã khai báo. Để gọi các phương thức bạn dùng <Tên biến>.<tên hàm hoặc tên biến>

Code cụ thể và minh họa cho ví dụ bên trên về hình chử nhật

File Rectangle.h

1

2

3

4

5

6

7

8

9

10

11

12

13

class

Rectangle

{

private

:

    

int

width

;

    

int

length

;

public

:

    

void

set

(

int

w

,

int

l

)

;

    

int

area

(

)

;

    

    

Rectangle

(

)

;

    

~

Rectangle

(

)

;

    

Rectangle

(

int

w

,

int

l

)

;

}

;

File Rectangle.cpp

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

#include “Rectangle.h”

 

Rectangle

::

Rectangle

(

)

{

    

width

=

1

;

    

length

=

1

;

}

 

Rectangle

::

Rectangle

(

int

w

,

int

l

)

{

    

width

=

w

;

    

length

=

l

;

}

 

Rectangle

::

~

Rectangle

(

)

{

}

 

void

Rectangle

::

set

(

int

w

,

int

l

)

{

    

width

=

w

;

    

length

=

l

;

}

 

int

Rectangle

::

area

(

)

{

    

return

width*

length

;

}

File Main.cpp

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

#include <iostream>

#include “Rectangle.h”

using

namespace

std

;

 

int

main

(

)

{

    

Rectangle

hcn

;

    

cout

<<

hcn

.

area

(

)

<<

endl

;

 

    

Rectangle

hcn1

(

10

,

20

)

;

    

cout

<<

hcn1

.

area

(

)

<<

endl

;

 

 

    

system

(

“pause”

)

;

}

Kết quả chạy thử chương trình trên

6. Bài tập ứng dụng code Class căn bản

Các bạn hãy tự rèn thêm bằng cách code các đối tương như phân số, sẽ có thuộc tính tử mẫu, các phương thức như nhập, in ra màn hình, cộng trừ 2 phân số, v.v…

Ngoài ra có thể xem thêm một bài tập hoàn chỉnh có lời giải tại đây

Nếu có thắc mắc nào vui lòng comment tại đây.