Các mở rộng cử C++
Các từ khóa mới của C++ Để bổ sung các tính năng mới vào C, một số từ khóa (keyword) mới đã được đưa vào C++ ngoài các từ khóa có trong C. Các chương trình bằng C nào sử dụng các tên trùng với các từ khóa cần phải thay ...
Các từ khóa mới của C++
Để bổ sung các tính năng mới vào C, một số từ khóa (keyword) mới đã được đưa vào C++ ngoài các từ khóa có trong C. Các chương trình bằng C nào sử dụng các tên trùng với các từ khóa cần phải thay đổi trước khi chương trình được dịch lại bằng C++. Các từ khóa mới này là :
| asm | catch | class | delete | friend | inline |
| new | operator | private | protected | public | template |
| this | throw | try | virtual |
Cách ghi chú thích
C++ chấp nhận hai kiểu chú thích. Các lập trình viên bằng C đã quen với cách chú thích bằng /*…*/. Trình biên dịch sẽ bỏ qua mọi thứ nằm giữa /*…*/.
Ví dụ 2.1: Trong chương trình sau :
|
||
CT2_1.CPP 1: /*2: Chương trình in các số từ 0 đến 9.3: */4: #include <iostream.h>5: int main()6: {7: int I;8: for(I = 0; I < 10 ; ++ I)// 0 - 99: cout<<I<<"
"; // In ra 0 - 910: return 0;11: }![]() ![]() |
||
|
||
|
Mọi thứ nằm giữa /*…*/ từ dòng 1 đến dòng 3 đều được chương trình bỏ qua. Chương trình này còn minh họa cách chú thích thứ hai. Đó là cách chú thích bắt đầu bằng // ở dòng 8 và dòng 9. Chúng ta chạy ví dụ 2.1, kết quả ở hình 2.1.
Hình 2.1: Kết quả của ví dụ 2.1
Nói chung, kiểu chú thích /*…*/ được dùng cho các khối chú thích lớn gồm nhiều dòng, còn kiểu // được dùng cho các chú thích một dòng.
Dòng nhập/xuất chuẩn
Trong chương trình C, chúng ta thường sử dụng các hàm nhập/xuất dữ liệu là printf() và scanf(). Trong C++ chúng ta có thể dùng dòng nhập/xuất chuẩn (standard input/output stream) để nhập/xuất dữ liệu thông qua hai biến đối tượng của dòng (stream object) là cout và cin.
Ví dụ 2.2: Chương trình nhập vào hai số. Tính tổng và hiệu của hai số vừa nhập.
|
||
CT2_2.CPP 1: #include <iostream.h>2: int main()3: {4: int X, Y;5: cout<< "Nhap vao mot so X:";6: cin>>X;7: cout<< "Nhap vao mot so Y:";8: cin>>Y;9: cout<<"Tong cua chung:"<<X+Y<<"
";10: cout<<"Hieu cua chung:"<<X-Y<<"
";11: return 0;12: }![]() ![]() |
||
|
||
|
Để thực hiện dòng xuất chúng ta sử dụng biến cout (console output)kết hợp với toán tử chèn (insertion operator) << như ở các dòng 5, 7, 9 và 10. Còn dòng nhập chúng ta sử dụng biến cin (console input) kết hợp với toán tử trích (extraction operator) >> như ở các dòng 6 và 8. Khi sử dụng cout hay cin, chúng ta phải kéo file iostream.h như dòng 1. Chúng ta sẽ tìm hiểu kỹ về dòng nhập/xuất ở chương 8. Chúng ta chạy ví dụ 2.2 , kết quả ở hình 2.2.
Hình 2.2: Kết quả của ví dụ 2.2
Hình 2.3: Dòng nhập/xuất dữ liệu
Cách chuyển đổi kiểu dữ liệu
Hình thức chuyển đổi kiểu trong C tương đối tối nghĩa, vì vậy C++ trang bị thêm một cách chuyển đổi kiểu giống như một lệnh gọi hàm.
Ví dụ 2.3:
|
||
CT2_3.CPP 1: #include <iostream.h>2: int main()3: {4: int X = 200;5: long Y = (long) X; //Chuyển đổi kiểu theo cách của C 6: long Z = long(X); // Chuyển đ ổi kiểu theo cách mới của C++7: cout<< "X = "<<X<<"
";8: cout<< "Y = "<<Y<<"
";9: cout<< "Z = "<<Z<<"
";10: return 0;11: }![]() ![]() |
||
|
||
|
Chúng ta chạy ví dụ 2.3 , kết quả ở hình 2.4.
Hình 2.4: Kết quả của ví dụ 2.3
Vị trí khai báo biến
Trong chương trình C đòi hỏi tất cả các khai báo bên trong một phạm vi cho trước phải được đặt ở ngay đầu của phạm vi đó. Điều này có nghĩa là tất cả các khai báo toàn cục phải đặt trước tất cả các hàm và các khai báo cục bộ phải được tiến hành trước tất cả các lệnh thực hiện. Ngược lại C++ cho phép chúng ta khai báo linh hoạt bất kỳ vị trí nào trong một phạm vi cho trước (không nhất thiết phải ngay đầu của phạm vi), chúng ta xen kẽ việc khai báo dữ liệu với các câu lệnh thực hiện.
Ví dụ 2.4: Chương trình mô phỏng một máy tính đơn giản
|
||
CT2_4.CPP 1: #include <iostream.h>2: int main()3: {4: int X;5: cout<< "Nhap vao so thu nhat:";6: cin>>X;7: int Y;8: cout<< "Nhap vao so thu hai:";9: cin>>Y;10: char Op;11: cout<<"Nhap vao toan tu (+-*/):";12: cin>>Op;13: switch(Op)14: {15: case ‘+’:16: cout<<"Ket qua:"<<X+Y<<"
";17: break;18: case ‘-’:19: cout<<"Ket qua:"<<X-Y<<"
";20: break;21: case ‘*’:22: cout<<"Ket qua:"<<long(X)*Y<<"
";23: break;24: case ‘/’:25: if (Y)26: cout<<"Ket qua:"<<float(X)/Y<<"
";27: else28: cout<<"Khong the chia duoc!" <<"
"; 9; 9; 29: break;30: default :31: cout<<"Khong hieu toan tu nay!"<<"
";32: }33: return 0;34: }![]() ![]() |
||
|
||
|
Trong chương trình chúng ta xen kẻ khai báo biến với lệnh thực hiện ở dòng 4 đến dòng 12. Chúng ta chạy ví dụ 2.4, kết quả ở hình 2.5.
Hình 2.5: Kết quả của ví dụ 2.4
Khi khai báo một biến trong chương trình, biến đó sẽ có hiệu lực trong phạm vi của chương trình đó kể từ vị trí nó xuất hiện. Vì vậy chúng ta không thể sử dụng một biến được khai báo bên dưới nó.
Các biến const
Trong ANSI C, muốn định nghĩa một hằng có kiểu nhất định thì chúng ta dùng biến const (vì nếu dùng #define thì tạo ra các hằng không có chứa thông tin về kiểu). Trong C++, các biến const linh hoạt hơn một cách đáng kể:
C++ xem const cũng như #define nếu như chúng ta muốn dùng hằng có tên trong chương trình. Chính vì vậy chúng ta có thể dùng const để quy định kích thước của một mảng như đoạn mã sau:
const int ArraySize = 100;
int X[ArraySize];
Khi khai báo một biến const trong C++ thì chúng ta phải khởi tạo một giá trị ban đầu nhưng đối với ANSI C thì không nhất thiết phải làm như vậy (vì trình biên dịch ANSI C tự động gán trị zero cho biến const nếu chúng ta không khởi tạo giá trị ban đầu cho nó).
Phạm vi của các biến const giữa ANSI C và C++ khác nhau. Trong ANSI C, các biến const được khai báo ở bên ngoài mọi hàm thì chúng có phạm vi toàn cục, điều này nghĩa là chúng có thể nhìn thấy cả ở bên ngoài file mà chúng được định nghĩa, trừ khi chúng được khai báo là static. Nhưng trong C++, các biến const được hiểu mặc định là static.
Về struct, union và enum
Trong C++, các struct và union thực sự các các kiểu class. Tuy nhiên có sự thay đổi đối với C++. Đó là tên của struct và union được xem luôn là tên kiểu giống như khai báo bằng lệnh typedef vậy. Trong C, chúng ta có thể có đoạn mã sau :
struct Complex
{
float Real;
float Imaginary;
};
…………………..
struct Complex C;
Trong C++, vấn đề trở nên đơn giản hơn:
struct Complex
{
float Real;
float Imaginary;
};
…………………..
Complex C;
Quy định này cũng áp dụng cho cả union và enum. Tuy nhiên để tương thích với C, C++ vẫn chấp nhận cú pháp cũ.
Một kiểu union đặc biệt được thêm vào C++ gọi là union nặc danh (anonymous union). Nó chỉ khai báo một loạt các trường(field) dùng chung một vùng địa chỉ bộ nhớ. Một union nặc danh không có tên tag, các trường có thể được truy xuất trực tiếp bằng tên của chúng. Chẳng hạn như đoạn mã sau:
union
{
int Num;
float Value;
};
Cả hai Num và Value đều dùng chung một vị trí và không gian bộ nhớ. Tuy nhiên không giống như kiểu union có tên, các trường của union nặc danh thì được truy xuất trực tiếp, chẳng hạn như sau:
Num = 12;
Value = 30.56;
Toán tử định phạm vi
Toán tử định phạm vi (scope resolution operator) ký hiệu là ::, nó được dùng truy xuất một phần tử bị che bởi phạm vi hiện thời.
Ví dụ 2.5 :
|
||
CT2_5.CPP 1: #include <iostream.h>2: int X = 5;3: int main()4: {5: int X = 16;6: cout<< "Bien X ben trong = "<<X<<"
";7: cout<< "Bien X ben ngoai = "<<::X<<"
";8: return 0;9: }![]() ![]() |
||
|
||
|
Chúng ta chạy ví dụ 2.5, kết quả ở hình 2.6
Hình 2.6: Kết quả của ví dụ 2.5
Toán tử định phạm vi còn được dùng trong các định nghĩa hàm của các phương thức trong các lớp, để khai báo lớp chủ của các phương thức đang được định nghĩa đó. Toán tử định phạm vi còn có thể được dùng để phân biệt các thành phần trùng tên của các lớp cơ sở khác nhau.







































