5.6.Phạm vi biến
Biến cục bộ trong C++
Các biến được khai báo bên trong một hàm hoặc khối là các biến cục bộ (local). Chúng chỉ có thể được sử dụng bởi các lệnh bên trong hàm hoặc khối code đó. Các biến cục bộ khơng được biết ở bên ngồi hàm đó (tức là chỉ được sử dụng bên trong hàm hoặc khối code đó). Dưới đây là ví dụ sử dụng các biến cục bộ:
#include<iostream> usingnamespace std; int main ()
// phan khai bao bien cuc bo: int a, b;
int c;
// phan khoi tao bien a =10; b =20; c = a + b; cout << c; return0; } 6.Mảng một chiều
6.1.Khai báo và khởi tạo mảng
Khai báo mảng trong C/C++
Để khai báo một mảng trong ngôn ngữ C/C++, bạn xác định kiểu của biến và số lượng các phần tử được yêu cầu bởi biến đó như sau:
KieuTen_mang[Kich_co_mang];
Đây là mảng một chiều.Kich_co_mang phải là một số nguyên lớn hơn 0 vàKieu phải
hợp lệ trong ngôn ngữ C/C++. Ví dụ, khai báo một mảng 10 phần tử gọi là balance với kiểu double, sử dụng câu lệnh sau đây:
char sinhvien[10];
6.2.Một số thao tác với mảng một chiều
Khởi tạo mảng trong C/C++
Bạn có thể khởi tạo mảng trong C/C++ hoặc từng phần tử một hoặc sử dụng một câu lệnh như dưới đây:
int hanghoa[5]={45,34,29,67,49};
Số lượng các giá trị trong dấu ngoặc kép {} không được lớn hơn số lượng phần tử khai báo trong dấu ngoặc vng [].
Nếu bạn bỏ sót kích cỡ mảng thì mảng đó đủ lớn để giữ các giá trị được khởi tạo: Bạn sẽ tạo chính xác một chuỗi có giá trị giống hệt chuỗi bên trên bằng cách gán từng phần tử một. Dưới đây là một ví dụ khi gán giá trị cho một phần tử của mảng:
int hanghoa[]={45,34,29,67,49};
Bạn có thể tạo ra cùng một mảng giống như đã làm trong ví dụ trước. hanghoa[4]=50;
Câu lệnh bên trên gán giá trị thứ 5 của mảng giá trị 50.0. Tất cả các mảng đều có chỉ số (index) đầu tiên bằng 0, đây được gọi là chỉ số cơ bản và phần tử cuối cùng của mảng có chỉ số bằng độ lớn của mảng trừ đi 1. Dưới đây là cách biểu diễn hình họa cho chuỗi khai báo bên trên thông qua chỉ số:
Truy cập các phần tử mảng trong C/C++
Một mảng được truy cập bởi cách đánh chỉ số trong tên của mảng. Dưới đây là một cách truy cập một giá trị của mảng:
int hocphi= hocphik60[55];
Câu lệnh trên lấy phần tử thứ 56 của mảng và gán giá trị này cho biến hocphi. Dưới đây là một ví dụ về việc sử dụng với tất cả mô tả bên trên:
#include<iostream> usingnamespace std; #include<iomanip> using std::setw; int main() {
int n[10];// n la mot mang gom 10 so nguyen
// khoi tao gia tri cac phan tu cua mang n la 0
for(int i=0; i<10; i++) {
n[ i]= i+100;// thiet lap phan tu tai vi tri i la i + 100 }
cout<<"Phan tu thu:"<< setw(13)<<"Gia tri la:"<< endl;
// hien thi gia tri cua moi phan tu
for(int j=0; j<10; j++) {
cout<< setw(7)<< j<< setw(13)<< n[ j]<< endl; }
return0;
}
Bài tập thực hành
1. Viết chương trình C++ giải phương trình bậc 2: ax2
+ bx + c = 0.
2. Viết chương trình C++ tìm ước số chung lớn nhất (UCLN) và bội số chung nhỏ nhất (BCNN) của hai số a và b.
3. Viết chương trình C++ liệt kê tất cả các số nguyên tố nhỏ hơn n. 4. Viết chương trình C++ liệt kê n số nguyên tố đầu tiên.
5. Viết chương trình C++ liệt kê tất cả các số nguyên tố có 5 chữ số.
6. Viết chương trình C++ phân tích số nguyên n thành các thừa số nguyên tố. Ví dụ: 12 = 2 x 2 x 3.
7. Viết chương trình C++ tính tổng các chữ số của một số nguyên n. Ví dụ: 1234 = 1 + 2 + 3 + 4 = 10.
8. Viết chương trình C++ tìm các số thuận nghịch có 6 chữ số. Một số được gọi là số thuận nghịch nếu ta đọc từ trái sang phải hay từ phải sang trái số đó ta vẫn nhận được một số giống nhau. Ví dụ 123321 là một số thuận nghịch.
9. Nhập số tự nhiên n. Hãy liệt kê các số Fibonacci nhỏ hơn n là số nguyên tố.
10. Dãy số Fibonacci được định nghĩa như sau: F0 = 0, F1 = 1, F2 = 1, Fn = F(n-1) + F(n- 2) với n >= 2. Ví dụ: 0, 1, 1, 2, 3, 5, 8, ... Hãy viết chương trình tìm số Fibonacci thứ n.
BÀI 3: ĐĨNG GĨI VÀ XÂY DỰNG LỚP, TẠO VÀ SỬ DỤNGMã bài: MĐCNTT 21.03 Mã bài: MĐCNTT 21.03
Giới thiệu
Data encapsulation là một kỹ thuật đóng gói dữ liệu, và các hàm mà sử dụng chúng và trừu tượng hóa dữ liệu là một kỹ thuật chỉ trưng bày tới các Interface và ẩn Implementation Detail (chi tiết trình triển khai) tới người sử dụng.C++ hỗ trợ các thuộc tính của đóng gói và ẩn dữ liệu thơng qua việc tạo các kiểu tự định nghĩa (user-defined), gọi là classes. Chúng ta đã học rằng một lớp có thể chứa các thành viênprivate, protected vàpublic. Theo mặc định, tất cả thành phần được định nghĩa trong một lớp là
private
Mục tiêu
Hiểu và biết cách xây dựng lớp; tạo và sử dụng đối tượng thể hiện các kỹ thuật trừu tượng hóa dữ liệu; đóng gói và che giấu thơng tin.
Nội dung
1.Trừu tượng hóa dữ liệu
1.1.Trừu tượng hóa dữ liệu là gì? 1.2.Trừu tượng hóa dữ liệu là gì?
Trừu tượng hóa dữ liệu (Data abstraction) liên quan tới việc chỉ cung cấp
thông tin cần thiết tới bên ngoài và ẩn chi tiết cơ sở của chúng, ví dụ: để biểu diễn thơng tin cần thiết trong chương trình mà khơng hiển thị chi tiết về chúng.
Trừu tượng hóa dữ liệu (Data abstraction) là một kỹ thuật lập trình mà dựa trên sự phân biệt của Interface và Implementation (trình triển khai).
Xem xét ví dụ về một chiếc TV, bạn có thể bật/tắt, thay đổi kênh, chỉnh âm lượng, và thêm các thiết bị ngoại vi như loa, VCR và DVD. Nhưng bạn không biết các chi tiết nội vi của nó, đó là, bạn khơng biết cách nó nhận tín hiệu qua khơng khí hoặc qua dây cáp, cách phiên dịch chúng và cuối cùng là hiển thị chúng trên màn hình.
Vì thế, có thể nói rằng một chiếc TV phân biệt rõ ràng trình triển khai nội vi của nó với giao diện ngoại vi và bạn có thể thao tác với interface với các nút nguồn, điều khiển âm lượng mà khơng cần có bất kỳ hiểu biết về những gì diễn ra bên trong nó.
Bây giờ, về mặt ngơn ngữ lập trình C++, thì các lớp C++ cung cấp Trừu tượng hóa dữ liệu (Data abstraction) ở mức thật tuyệt vời. Chúng cung cấp đủ các phương thức public tới bên ngoài để thao tác với tính năng của đối tượng và để thao tác dữ liệu đối tượng, ví dụ: trạng thái mà khơng cần thực sự biết về cách lớp đó đã được triển khai nội tại.
Ví dụ, chương trình của bạn có thể tạo một lời gọi tới hàmsort() mà khơng cần biết
về hàm đó thực sự sử dụng thuật tốn gì để sắp xếp các giá trị đã cho. Thực ra, trình triển khai cơ sở (underlying implementation) của tính năng sắp xếp có thể thay đổi tùy vào thư viện, và miễn là Interface vẫn như cũ thì lời gọi hàm của bạn vẫn tiếp tục làm việc.
Trong C++, chúng ta sử dụng cácLớp để định nghĩa kiểu dữ liệu trừu tượng (abstract
data types (ADT)) của riêng chúng ta. Bạn có thể sử dụng đối tượng cout của lớpostream cho luồng dữ liệu tới đầu ra chuẩn như sau:
1 2 3 4 #include <iostream> using namespace std; int main( ) {
5 cout << "Hello C++" <<endl; return 0;
}
1.3.So sánh đối tượng và lớp
Object
Trong C++, Đối tượng (Object) là một thực thể trong thế giới thực, ví dụ, ghế, xe hơi, bút, điện thoại, máy tính xách tay, v.v.
Nói cách khác, đối tượng là một thực thể có trạng thái và hành vi. Ở đây, trạng thái có nghĩa là dữ liệu và hành vi có nghĩa là chức năng.
Đối tượng là một thể hiện của một lớp. Tất cả các thành viên của lớp có thể được truy cập thơng qua đối tượng.
Ví dụ sau tạo đối tượng của lớp Student bằng cách sử dụng s1 làm biến tham chiếu. Student s1; // lệnh tạo đối tượng sinh viên trong ví dụ này Student là kiểu và s1 là biến tham chiếu đến cá thể của lớp student
Class
Trong C++, Lớp (class) là một nhóm các đối tượng tương tự. Nó là một khn mẫu mà từ đó các đối tượng được tạo ra. Nó có thể có các trường, phương thức, constructor, ... Hãy xem một ví dụ về lớp C++ chỉ có ba trường.
classStudent { public:
intid; // truong hoac thanh vien du lieu floatsalary; // truong hoac thanh vien du lieu String name; // truong hoac thanh vien du lieu }
Ví dụ lớp và đối tượng trong C++
#include <iostream> usingnamespacestd; classStudent { public: intid; string name; }; intmain() {
Student s1; // tao doi tuong Student s1.id = 10001;
s1.name = "Vinh Tran"; cout << s1.id << endl; cout << s1.name << endl; return0;
} Kết quả: 10001 Vinh Tran
2. Đóng gói và xây dựng lớp
2.1. Đóng gói là gì?
• Các lệnh (code) chương trình: Đây là phần chương trình mà thực hiện các hành
động và cúng được gọi là các hàm.
• Dữ liệu chương trình: Dữ liệu là thơng tin của chương trình mà tác động đến các
hàm chương trình.
Tính đóng gói (Encapsulation) là một khái niệm của lập trình hướng đối tượng mà ràng buộc dữ liệu và các hàm mà thao tác dữ liệu đó, và giữ chúng an tồn bởi ngăn cản sự gây trở ngại và sự lạm dụng từ bên ngồi. Tính đóng gói dẫn đến khái niệm OOP quan trọng làData Hiding.
Tính đóng gói - Data encapsulation là một kỹ thuật đóng gói dữ liệu, và các hàm mà
sử dụng chúng và trừu tượng hóa dữ liệu là một kỹ thuật chỉ trưng bày tới các Interface và ẩn Implementation Detail (chi tiết trình triển khai) tới người sử dụng.
C++ hỗ trợ các thuộc tính của đóng gói và ẩn dữ liệu thông qua việc tạo các kiểu tự định nghĩa (user-defined), gọi là classes. Chúng ta đã học rằng một lớp có thể chứa các thành viênprivate, protected và public. Theo mặc định, tất cả thành phần được định nghĩa
trong một lớp là private. Ví dụ: ? 1 2 3 4 5 6 7 8 9 10 11 12 classBox { public: doubletinhTheTich(void) {
returnchieudai * chieurong * chieucao; }
private:
doublechieudai; // Chieu dai cua mot box doublechieurong; // Chieu rong cua mot box doublechieucao; // Chieu cao cua mot box };
Các biếnchieudai, chieurong, và chieucao làprivate. Nghĩa là chúng chỉ có thể được
truy cập bởi các thành viên khác của lớp Box, và không thể bởi bất kỳ phần khác trong chương trình của bạn. Đây là một cách thực hiện tính đóng gói trong C++.
Để làm cho các phần của lớp làpublic (ví dụ: có thể truy cập tới các phần khác trong
chương trình của bạn), bạn phải khai báo chúng sau từ khóapublic. Tất cả biến và hàm
được định nghĩa sau từ khóa public là có thể truy cập cho tất cả các hàm trong chương trình của bạn.
2.2. Xây dựng lớp
Lớp (Class) là cách phân loại (classify) các đối tượng dựa trên đặc điểm chung của các đối tượng đó.
• Lớp có thể coi là khn mẫu để tạo các đối tượng − Ví dụ: Người, Sinh Vật, Màu sắc…
• Lớp chính là kết quả của q trình trừu tượng hóa dữ liệu
− Lớp định nghĩa một kiểu dữ liệu mới, trừu tượng hóa một tập các đối tượng − Một đối tượng gọi là một thể hiện của lớp
2.3. Che giấu dữ liệu
Đóng gói là một khái niệm trong lập trình hướng đối tượng, kết hợp giữa dữ liệu và các hàm thao tác dữ liệu với nhau, đồng thời đảm bảo sự an toàn và tránh khỏi sự can thiệp và sử dụng sai cách. Nó liên quan đến việc đóng gói các thành viên dữ liệu và các chức năng bên trong một lớp duy nhất. Đóng gói dữ liệu liên quan tới một khái niệm khác đó là che giấu dữ liệu.
Nói chung, đóng gói là một q trình gói các đoạn mã tương tự vào cùng một nơi. Tính năng đóng gói dữ liệu là một cơ chế đóng gói dữ liệu và các hàm sử dụng dữ liệu. Trừu tượng hóa dữ liệu là cơ chế chỉ để cho phép hiện ra các giao diện và ẩn dấu đi các chi tiết bên trong khỏi người dùng.
C ++ hỗ trợ các thuộc tính đóng gói và che giấu dữ liệu thơng qua việc tạo ra các kiểu dữ liệu do người dùng tự định nghĩa, được gọi là các lớp hay Class. Một lớp có thể chứa các thành viên trong phạm vi Private, Protected và Public. Theo mặc định, tất cả các thành viên sẽ được xác định trong phạm vi là Private.
2.4. Phương thức set/get
3. Tạo và sử dụng đối tượng
3.1. Khởi tạo dữ liệu
Đây là cách khai báo các biến có cùng kiểu dữ liệu trên cùng một dòng đồng thời khởi tạo giá trị ban đầu cho mỗi biến.Khi khai báo nhiều biến trên cùng 1 dòng, mỗi biến được khai báo sẽ cách nhau bằng 1 dấu phẩy. Điều này hoàn toàn được cho phép trong
C++.
int number1 =4, number2 = 5;
3.2.Phương thức khởi tạo
Hiện tại C++11 trở về sau hỗ trợ 3 loại constructor với mục đích sử dụng khác nhau nhằm tối ưu hóa cho từng trường hợp sử dụng cụ thể:
• Constructor: hàm tạo khởi tạo mới. • Copy constructor: hàm tạo sao chép. • Move constructor: hàm tạo dịch chuyển.
Ứng với 3 tên gọi này là mục đích sử dụng của nó. Cả 3 phương thức đều tự động gọi khi đối tượng được tạo ra.
3.3.Khai báo và khởi tạo đối tượng
Hàm khởi tạo (constructor) là một phương thức đặc biệt được gọi tự động tại thời điểm
đối tượng được tạo. Mục đích củahàm khởi tạo là để khởi tạo các thành viên dữ liệu của
đối tượng.
Mộthàm khởi tạo sẽ khác những hàm thơng thường ở những điểm sau:
• Có tên trùng với tên lớp
• Khơng có kiểu dữ liệu trả về ( kể cả kiểuvoid)
• Tự động được gọi khi một đối tượng thuộc lớp được tạo ra
• Nếu chúng ta khơng khai báo mộthàm khởi tạo, trình biên dịch C++ sẽ tự động
tạo mộthàm khởi tạo mặc định cho chúng ta (sẽ là hàm khơng có tham số nào và
có phần thân trống).
3.4.Sử dụng đối tượng
Xét ví dụ sau #include <string.h> class Matrix4x4
{ private: double* data; public: Matrix4x4() {
data = new double[4 * 4]; }
Matrix4x4(const Matrix4x4& matrix) {
data = new double[4 * 4];
memcpy(data, matrix.data, sizeof(double) * 4 * 4); } Matrix4x4(Matrix4x4&& matrix) { data = matrix.data; matrix.data = nullptr; } ~Matrix4x4() { if (data != nullptr) delete[] data; }
Matrix4x4& operator=(const Matrix4x4& matrix) {
memcpy(data, matrix.data, sizeof(double) * 4 * 4); return *this;
}
Copy constructor được sử dụng trong trường hợp tạo các giá trị mới nhưng cần sao chép ngay các dữ liệu của đối tượng có sẵn thay vì gọi constructor tốn kém hiệu năng và rồi gọi phương thức sao chép tốn kém thêm 1 lần hiệu năng nữa.
1 trường hợp điển hình sử dụng copy constructor thuận tiện là hoán đổi giá trị của 2 Matrix4x4 khi cần khai báo 1 Matrix4x4 temp.
Matrix4x4 temp = m1; m1 = m2;
m2 = temp;
Dòng Matrix4x4 temp = m1 gọi copy constructor khi khởi tạo temp, trường hợp này dùng vậy rất thuật tiện và đỡ tốn hiệu năng.
Matrix4x4(Matrix4x4 && matrix)
Move constructor được gọi trong trường hợp khởi tạo đối tượng truyền vào 1 rvalue. Matrix4x4 m1, m2;
Matrix4x4 m3(m1 + m2);
Dòng Matrix4x4 m3(m1 + m2) trong đó m1 + m2 sẽ trả về 1 đối tượng tạm, sau dòng code này đối tượng đó sẽ hủy, trước C++11 chỉ có thể gọi copy constructor, m3 sẽ phải khởi khởi tạo vùng nhớ và sao chép dữ liệu từ đối tượng m1 + m2 dù biết rằng m1 + m2 sẽ không dùng nữa nhưng vẫn khơng thể "chiếm dụng" kết quả này, nhưng với C++11 thì khác, có thể tiến hành gọi move constructor vì biết m1 + m2 là rvalue, như phần hiện thực của move constructor có thể thấy dữ liệu tạm được "sang nhượng" cho m3. với chi phí thấp hơn copy constructor.
Matrix4x4 operator+(const Matrix4x4& matrix) {
Matrix4x4 result = *this; for (int i = 0; i < 4 * 4; i++) result.data[i] += matrix.data[i]; return result; } }; int main() { Matrix4x4 m1, m2; Matrix4x4 m3 = m1 + m2;