Lập trình hướng đối tượng - Chương 4: Các kỹ thuật xây dựng hàm, sử dụng biến, hằng trong Lập trình hướng đối tượng - Huỳnh Quyết Thắng
Các biến địa phương khai báo cục bộ trong hàm:
– Trong trường hợp các biến địa phương không khai
báo là biến static thì mỗi lần gọi hàm chương trình
dịch lại đăng ký tạo ra biến mới
– Khi chúng ta khai báo các biến địa phương là các biến
static thì chương trình dịch sẽ chỉ khởi tạo duy nhất
một lần (ở lần gọi đầu tiên) biến địa phương này và
thông qua con trỏ stack ở những lần gọi sau chi tham
chiếu tới biến đã tạo ra này để sử dụng lại chúng mà
không tạo ra biến mới
Tạo một lần/tham chiếu nhiều lần/lưu giá trị của
lần tham chiếu trước
) { return ++x; } Các hàm được định nghĩa trong thân của một lớp được tự động trở thành các hàm inline. Tuy nhiên bạn có thể làm cho một hàm của một lớp trở thành inline mà không cần định nghĩa nó trong thân lớp bằng cách đặt từ “inline” vào định nghĩa hàm. TS H.Q. Thắng - TS C.T. Dũng CNPM 36 Hàm Inline Khi bạn tạo một lời gọi tới một hàm inline, đầu tiên trình biên dịch phải kiểm tra chắc chắn rằng lời gọi đó được tạo ra một cách đúng đắn. Nếu tất cả các thông tin về kiểu hàm hợp với ngữ cảnh của lời gọi thì mã inline sẽ được thay thế trực tiếp vào chỗ gọi hàm. Từ đó ta thấy rằng một hàm inline phải được định nghĩa trước khi nó được sử dụng 19 TS H.Q. Thắng - TS C.T. Dũng CNPM 37 Hàm Inline Nếu hàm inline chứa các lệnh điều khiển chương trình phức tạp ví dụ như các cấu trúc lặp, rẽ nhánh thì copiler sẽ bỏ qua tính inline của hàm. Ta chỉ nên dùng hàm inline để chứa các lệnh gán, biểu thức và lệnh gọi hàm đơn giản. Compiler có thể bỏ qua từ khóa inline nếu như nó thấy cần thiết. Ví dụ như trong chương trình của ta có quá nhiều lời gọi tới các hàm inline thì compiler sẽ bỏ qua tính inline của hàm xì thiếu bộ nhớ hoặc nếu các hàm inline dài, và các hàm đệ quy thì không thể là inline. So sánh hàm Inline và hàm thường? TS H.Q. Thắng - TS C.T. Dũng CNPM 38 class CStr { char *pData; int nLength; public: //implicit inline function char *get_Data(void) {return pData; } int getlength(void); }; //explicit inline function inline void CStr::getlength(void) { return nLength; } 20 TS H.Q. Thắng - TS C.T. Dũng CNPM 39 Hàm Inline Tổng kết về hàm inline: – Ưu điểm: việc sử dụng hàm inline có tác dụng tiết kiệm được thời gian không phải thực hiện các xử lý đầu vào khi gọi hàm như: đẩy đối số vào stack, tạo một lời gọi, sau đó khi trở về thì phải giải toả các tham số khỏi stack. Trong nhiều trường hợp mã của nó nhỏ hơn so với việc nếu nó được cấp phát trên ngăn xếp. – Nhược điểm: làm cho chương trình lớn hơn. Việc sử dụng nhiều lời gọi tới hàm inline và các hàm inline dài sẽ làm cho chương trình bị phình to. TS H.Q. Thắng - TS C.T. Dũng CNPM 40 Kỹ thuật chồng hàm trong LTHDT Ý tưởng của nguyên lý chồng hàm: cho phép đặt tên hàm trùng nhau để mô tả bản chất công việc, nhưng các đối số hoặc kiểu dữ liệu trả về từ hàm là khác nhau Căn cứ vào số lượng hoặc kiểu dữ liệu của các giá trị truyền cho đối số HĐH sẽ chọn ra hàm phù hợp nhất để thực hiện trong trường hợp chồng hàm. Nếu như không chọn được hoặc chọn được >1 (hai hàm trở lên) như vậy thì sẽ báo lỗi. 21 TS H.Q. Thắng - TS C.T. Dũng CNPM 41 Kỹ thuật chồng hàm trong LTHDT Phân loại kỹ thuật chồng hàm: – Chồng hàm dựa trên các đối số: số lượng và kiểu dữ liệu – Ví dụ: void f (int); void f (int, float); void f (); – Đặc điểm: Chấp nhận ở tất cả các ngôn ngữ lập trình hướng đối tượng TS H.Q. Thắng - TS C.T. Dũng CNPM 42 Kỹ thuật chồng hàm trong LTHDT Phân loại kỹ thuật chồng hàm: – Chồng hàm dựa trên kiểu dữ liệu trả về từ hàm. Ví dụ: void f(int); int f(int); float f(int); – Đặc điểm: Khó thực hiện chương trình dich, không chấp nhận trong các ngôn ngữ lập trình hướng đối tượng như C++ 22 TS H.Q. Thắng - TS C.T. Dũng CNPM 43 Chồng hàm Các điểm cần lưu ý về chồng hàm: – Các hàm được xem xét là chồng hàm nếu như chúng phải có cùng phạm vi (cùng trong một lớp, hoặc một mô-đun) – Các hàm phải có cùng tên hàm – Chỉ nên sử dụng khi các hàm có cùng mục đích, chức năng Chồng hàm thường được gặp nhất khi xây dựng các hàm thiết lập cho lớp TS H.Q. Thắng - TS C.T. Dũng CNPM 44 Java: định nghĩa chồng phương thức public class Ship4 { public double x=0.0, y=0.0, speed=1.0, direction=0.0; public String name; public Ship4(double x, double y, double speed, double direction, String name) { this.x = x; this.y = y; this.speed = speed; this.direction = direction; this.name = name; } public Ship4(String name) { this.name = name; } private double degreesToRadians(double degrees) { return(degrees * Math.PI / 180.0); } ... 23 TS H.Q. Thắng - TS C.T. Dũng CNPM 45 Java: định nghĩa chồng phương thức public void move() { move(1); } public void move(int steps) { double angle = degreesToRadians(direction); x = x + (double)steps * speed * Math.cos(angle); y = y + (double)steps * speed * Math.sin(angle); } public void printLocation() { System.out.println(name + " is at (" + x + "," + y + ")."); } } TS H.Q. Thắng - TS C.T. Dũng CNPM 46 Sử dụng phương thức định nghĩa chồng public class Test4 { public static void main(String[] args) { Ship4 s1 = new Ship4("Ship1"); Ship4 s2 = new Ship4(0.0, 0.0, 2.0, 135.0, "Ship2"); s1.move(); s2.move(3); s1.printLocation(); s2.printLocation(); } } 24 TS H.Q. Thắng - TS C.T. Dũng CNPM 47 Hàm có đối số mặc định (C++) Khai báo hàm void hamf (int x, float y=1.0) – ý nghĩa: đối số x là đối số không có giá trị mặc định, đối số y là đối số có giá trị mặc định – có thể có hai dạng gọi hàm func: func(10); đối số x nhận giá trị x=10 và đối số y nhận giá trị y=1.0 (giá trị mặc định) func(10, 5.0); đối số x nhận giá trị x=10 và đối số y nhận giá trị y=5.0 (giá trị truyền vào) Hàm với các đối số mặc định cho phép they đổi dạng của hàm khi truyền các giá trị/biến cho các đối số TS H.Q. Thắng - TS C.T. Dũng CNPM 48 Hàm có đối số mặc định (C++) Nguyên tắc khi khai báo hàm với đối số mặc định: – Để đảm bảo chương trình dịch xác định đúng giá trị/biến truyền cho các đối số chúng ta cần phải giữ nguyên tắc: Các đối số không có giá trị mặc định được xếp lên đầu danh sách của các đối số của hàm Các đối số có giá trị mặc định được xếp xuống cuối danh sách của các đối số của hàm void f (int x, int y, int a=0, float b=1.0) Gọi hàm: f(1, 2, 5) (x) (y) (a) (b)1 2 5 25 TS H.Q. Thắng - TS C.T. Dũng CNPM 49 Hàm có đối số mặc định (C++) int getSum(int, int=0, int=0);// OK int getSum(int, int=0, int); //wrong! Khi một đối số bị bỏ qua trong lời gọi hàm, tất cả đối số sau nó cũng phải bị bỏ qua. sum = getSum(num1, num2); // OK sum = getSum(num1, , num3);// wrong! Ngôn ngữ Java không hỗ trợ đặc tính này TS H.Q. Thắng - TS C.T. Dũng CNPM 50 Khi nào sử dụng ? Sử dụng hàm với các đối số có giá trị mặc định: – Thông thường công việc mà hàm đó thực hiện không thay đổi bản chất hay giải thuật thực hiện. Các đối số nhận các giá trị mặc định hay truyền vào chỉ làm thay đổi kết quả mà không thay đổi ý nghĩa công việc. – Trường hợp thứ hai nên sử dụng hàm có đối số giá trị mặc định: công việc trong hàm mang tính chất mở rộng trong những trường hợp đối số nhận những giá trị truyền vào 26 TS H.Q. Thắng - TS C.T. Dũng CNPM 51 Khi nào sử dụng ? Ví dụ (1): void f (int x, int y, int a=0, float b=1.0) – Công việc thực hiên trong f phụ thuộc vào 4 đối số x, y, a, b nhưng thông thường a=0 và b=1 tuy nhiên trong một số trường hợp a và b có thể nhận những giá trị khác Ví dụ (2): void f (int x, int y) – bình thường hàm f phụ thuộc vào hai giá trị đối số x,y. Bây giờ vì lý do phát triển mở rộng f phụ thuộc vào 3 đối số f(int x, int y, int a). – Làm thế nào có thể định nghĩa lại f mà trong chương trình những lời gọi cũ khi f có hai đối số không bị ảnh hưởng. Lời giải khai báo đối số a đối số với giá trị mặc định: – f (int x, int y, int a=0); TS H.Q. Thắng - TS C.T. Dũng CNPM 52 Hằng trong LTHDT Nguyên lý về hằng trong LTHDT thể hiện các đặc điểm và tư tưởng lập trình: những gì có thể thay đổi và những gì không được thay đổi và khi nào nên sử dụng chúng Trong các ngôn ngữ lập trình hướng đối tượng như có các từ khoá mang ý nghĩa khác nhau để sử dụng trong những trường hợp khai báo hằng số: – const (C++) – final (java) 27 TS H.Q. Thắng - TS C.T. Dũng CNPM 53 Con trỏ hằng Con trỏ tới một hằng: – const int * pi – Trong trường hợp này chúng ta khai báo rằng pi là một con trỏ và giá trị mà pi trỏ tới là một giá trị không đổi, không được phép sử dụng pi để thay đổi giá trị này – int a =10; int b=20; – pi=&a; //Lệnh đúng – pi=&b; //Lệnh đúng – *pi = 100; //Lệnh sai TS H.Q. Thắng - TS C.T. Dũng CNPM 54 Hằng con trỏ Hằng con trỏ – int const *pi – Trong trường hợp này chúng ta khai báo rằng pi là một con trỏ và là hằng tức là pi trỏ tới một địa chỉ không đổi, không được phép sử dụng pi để thay đổi địa chỉ mà pi trỏ tới – int a =10; int b=20; int const *pi = &a; – pi=&b; //Lệnh sai *pi = 100; //Lệnh đúng 28 TS H.Q. Thắng - TS C.T. Dũng CNPM 55 Sử dụng hằng trong hàm Truyền các đối số bằng từ khoá const – Khi khai báo hàm sử dụng các từ khóa const để khai báo các đối số trong hàm, chúng ta dã quy định luôn là trong thân hàm không thể sử dụng các lện thay đổi giá trị của các đối số này void f(const int n) { ..... n++; // Lỗi vì đã thay đổi giá trị của n .... } TS H.Q. Thắng - TS C.T. Dũng CNPM 56 Giá trị trả về từ hàm là hằng – Tương tự như trường hợp truyền các đối số, chúng ta cũng có thể khai báo hàm có giá trị trả về là hằng, tức là bên trong thân hàm không được phép thay đổi biến nằm ở lệnh return – Trên thực tế đối với các dữ liệu cơ bản giá trị trả về từ hàm không có ý nghĩa #include const int f(int &i) { i++; return (++i); } void main() { int d=1; d=f(d); cout<<d; } 29 TS H.Q. Thắng - TS C.T. Dũng CNPM 57 Hằng trong lớp Thành phần dữ liệu là hằng Các hàm thành phần có khai báo const sau danh sách tham số: – Không được quyền thay đổi thành phần dữ liệu của đối tượng trong lớp. Thường dùng cho các phương thức Get. – Làm việc trên các hằng đối tượng class Class { public: Class( int a0, int b0 ) ; void mf1() const; void mf2(); private: int a, b; }; void gf1 ( const Class &c ) ; void gf2 ( Class &c ) ; void main(void) { Class c1(1, 2) ; const Class c2(10, 20) ; c1.mf1 ( ) ; // OK c1.mf2 ( ) ; // OK gf1 ( c1 ) ; // OK gf2 ( c1 ) ; // OK c2.mf1 ( ) ; // OK c2.mf2 ( ) ; // Syntax error gf1 ( c2 ) ; // OK gf2 ( c2 ) ; // Syntax error }
File đính kèm:
- lap_trinh_huong_doi_tuong_chuong_4_cac_ky_thuat_xay_dung_ham.pdf