1. Trang chủ
  2. » Công Nghệ Thông Tin

Nguyễn mẫu hàm con trỏ hàm C++ nâng cao

29 454 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 29
Dung lượng 146,89 KB

Nội dung

Đây là 1 đoạn CT hoàn toàn đúng.Nhưng giả sử chúng ta muốn bảo trì CT rằngchúng ta muốn hoán vị 2 số thực kiễu float. Với hàm xây dựng sẵn như trên việc chúng ta truyền 2 biến kiểu float vào cho hàm sẽ bị lỗi biên dịch. Cách khác là chúng ta tạo ra riêng 1 hàm để hoán vị 2 kiểu khác chúng ta muốn nhưng cách này ko khả quan. Nếu 1 chương trình muốn hoán vị tới 10 kiểu khác nhau không lẽ ta phải tạo 1 0 hàm HoanVi. =>Code dài nhìn thiếu chuyên nghiệp, khó khăn trong việc bảo trì, nâng cấp.Rất maymắn C++ cho ra đời template function(khuôn mẫu hàm) để ta có thể thamsố hóa kiễu dữ liệu được truyền vào 1 hàm.Một hàm được tham số hóa là coi như là 1 hàm tổng quát xài chung cho mọi kiểudữ liệu từ cơ sơ cho đến kiễu dữ liệu định nghĩa.Chúng ta chỉ cần cài đặt hàm 1 lầnnhưng sử dụng được với nhiều kiểu dữ liệu .CÁCH THỰC HIỆN.Đối với những hàm chúng ta xác định rằng hàm đó sẽ có thể dùng chung đối vớimọi kiễu dữ liệu thì chúng ta sẽ đặt dòng template hoặctemplate, chúng giống nhau hoàn trong hai trường hợp trên tuynhiên có một số chỗ chúng ta buộc phải dùng class hoặc buộc phải dùngtypename. Ở đây ta sẽ chỉ dùng class T (theo tôi thấy được sử dụng rộng rãi hơn) Sau khi đã khai báo template cho hàm thì ta sẽ thay đổi kiễu dữ liệu trong hàmmà ta cho rằng chúng sẽlà 1 kiễu dữ liệu không biết trước bởi vì đối với hàm cóxây dựng template thì trình compile sẽ thực sự những biến đó thuộc kiễu dữ liệunào chỉ khi ta truyền biến vào hàm.

Trang 1

MỘT SỐ KIẾN THỨC NÂNG CAO TRONG C/C++

I.TEMPLATE FUNCTION(KHUÔN MẪU HÀM)

Trang 2

Rất maymắn C++ cho ra đời template function(khuôn mẫu hàm) để ta có thể tham

số hóa kiễu dữ liệu được truyền vào 1 hàm

Một hàm được tham số hóa là coi như là 1 hàm tổng quát xài chung cho mọi kiểu

dữ liệu từ cơ sơ cho đến kiễu dữ liệu định nghĩa.Chúng ta chỉ cần cài đặt hàm 1 lần nhưng sử dụng được với nhiều kiểu dữ liệu

Trang 3

- Sau khi đã khai báo template cho hàm thì ta sẽ thay đổi kiễu dữ liệu trong hàm

mà ta cho rằng chúng sẽlà 1 kiễu dữ liệu không biết trước bởi vì đối với hàm có

xây dựng template thì trình compile sẽ thực sự những biến đó thuộc kiễu dữ liệu

nào chỉ khi ta truyền biến vào hàm

VD ta sửa lại đoạn HoanVi trên cho nó có tính tham số hóa

template<class T> // T là tên kiễu dữ liệu coi như là chưa biết trước Các bạn có //thể đặt tên khác tùy ý

HoanVi(T &x, T &y) // Tôi thay kiểu int thành 1 kiểu T

C1: Gọi tường minh TenHam<kiểu dữ liệu truyền vào>(//Tham số nếu có)

C2: Gọi không tường mình thì như chúng ta gọi bình thường ^^ là như thế này

TenHam(//Tham số nếu có)

Theo kinh nghiệm của tôi thì trong 1 số trường hợp trình compile yêu cầu bạn phải

gọi tường minh đó ^^

CHÚ Ý 1: Chỉ khi ta xài các phương thức nhập xuất(cout và cin) của C++ thì mới

nên dùng template function

vì C++ việc nhập xuất không cần quan tâm đến đặc tả % của dữ liệu

Trang 4

VD đoạn dùng template function theo nhập xuất của thư viện <stdio.h> (standard input output của C )

như sau vẫn bị lỗi vì "vướng" phải đặc tả %

Trang 5

template<class T, class Y> // 2 kiểu T và Y

void Nhap2Bien(T &x, Y &y)

Trang 6

hóa nhưng ta cũng nên quản lý việc truyền kiểu dữ liệu 1 cách cẩn thận

Ví dụ về việc sử dụng tham số hóa không hợp lý

#include <iostream>

#include <conio.h>

#include <string> // Thư viện string của C++

using namespace std;

template<class T, class Y> // 2 kiểu T và Y

void Nhap2Bien(T &x, Y &y)

Trang 7

II CLASS TEMPLATE( KHUÔN MẪU LỚP)

1.Tham số hóa cho lớp

- Tương tự như khuôn mẫu hàm, khuôn mẫu lớp có cú pháp sử dụng như sau

VD1:

template<class T> // T hay tên gì khác tùy bạn đặt

Trang 8

Mang1Chieu<int> tendoituong;

2.Các tham số không kiểu

Chúng ta cũng có thể khai bao kiểu dữ liệu mặc định trong template

Trang 9

MyArray<int,50> a; // Mảng a có kiểu dữ liệu int với tối đa 50 phần tử

MyArray<HOCSINH, 100> h; // Mảng h có kiểu dữ liệu HOCSINH ( Gia sử ta //đã xây dựng class HOCSINH)// với tối đa 100 em

Ở hàm main ta chỉ việc khai báo MyArray<> tendoituong; thì trình compile cũng

tự xác định rằng Mảng tendoituong có kiểu dữ liệu int với tối đa 50 phần tử

3.Kế thừa các lớp tham số hóa

Trang 10

Khi 1 class dẫn xuất kế thừa 1 class cơ sở có sử dụng tham số hóa thì cú pháp như sau:

Trang 12

Biến đều có địa chỉ trong bộ nhớ

Vậy hàm tồn tại tức nó sẽ có địa chỉ trong bộ nhớ

=> Sẽ có 1 loại con trỏ trỏ đến các hàm Ta gọi là con trỏ hàm

Cú pháp:

<Kiểu trả về của hàm> (*<Tên con trỏ hàm>)(<Danh sách tham số nếu có>)

CHÚ Ý: Phần danh sách tham số ta chỉ cần quan tâm đến kiễu dữ liệu của tham số,

ko cần thiết khai tên tham số(giống khai báo hàm)

TRỎ ĐẾN HÀM: Chỉ có thể trỏ đến các hàm nếu con trỏ hàm phù hợp kiểu trả về, các ds tham số

Cách 1:

Trang 13

<Tên con trỏ> = <Tên hàm>;

Cách 2:

<Tên con trỏ> = &<Tên hàm>;

Sau khi trỏ thay vì gọi hàm bằng cách thông thường ta có thể thay tên hàm bằng tên con trỏ

VD1:

void Nhap2SoNguyen(int &x, int &y)

{

printf("Nhap x,y:\n");

scanf("%d%d", &x, &y);}

int TinhTong(int x, int y)

Trang 14

tham số kiểu int truyền theo kiểu tham chiếu ( tham biến).int (*p)(int , int ); // Khai //báo con trỏ hàm trỏ đến các hàm có kiểu trả là int với 2 tham số kiểu

// int truyền theo kiểu tham trị

q = TinhTong; // ERROR Ko phù hợp để trỏ

q = Nhap2SoNguyen; // OK con trỏ hàm q đang trỏ đến hàm Nhap2SoNguyen

q = &Nhap2SoNguyen; // OK con trỏ hàm q đang trỏ đến hàm Nhap2SoNguyen

p = TinhTong; // OK Con trỏ p trỏ đến hàm TinhTong

Trang 15

// Khai báo con trỏ hàm để có thể trỏ tới hàm HoanVi

float x,y;

x = 1;

y = 2;

void (*Pointer)(float*, float*);

// Có 2 cách cho con trỏ trỏ tới hàm

- Là mảng lưu giữ các phần tử là biến con trỏ hàm

CÚ PHÁP: KieuTraVe(*TenConTroHam[SoLuongphantu])(//Ds tham số nếu có)

Chú ý rằng các biến con trỏ của mảng phải cùng kiểu tra ve, DS tham số

VD:

int (*array[2])(int , int);

array[0] = TinhTong; // Con trỏ tại vị trí 0 trong mảng trỏ đến hàm TinhTong

array[1] = TinhHieu; // Con trỏ tại vị trí 1 trong mảng trỏ đến hàm TinhHieu

V KHUÔN MẪU HÀM, CON TRỎ HÀM TRONG VIỆC XÂY

DỰNG CHƯƠNG TRÌNH CÓ TÍNH CHẤT TÙY BIẾN MÃ NGUỒN

Trang 16

-Ta đã tìm hiểu về khuôn mẫu hàm, con trỏ hàm và các công dụng của chúng Và công dụng lớn nhất

của chúng theo đánh giá của tôi là sự kết hợp để tạo nên mã nguồn có tính tùy biến, ngắn gọn, dễ bảo trì

Ví dụ rằng ta có 2 hàm sắp xếp tăng dần và giảm dần mảng 1 chiều như sau:

void SapTang(int a[], int n)

Trang 17

tăng, vừa làm công việc sắp giảm được ko?

Câu trả lời rằng hãy ứng dụng con trỏ hàm như các ví dụ sau:

VD1:

//Ta tạo ra 2 hàm sosanh

//Nhắc lại về kiễu dữ liệu bool của C++:bool là kiểu dữ liệu do C++ xây dựng nên thuận tiện trong việc kiểm tra 1 điều kiện gì đó Nó trả ra 2 giá trị true hoặc false

bool SoSanhNho(int x, int y)

{

if(x > y)

Trang 19

int a[5] = {1, 5, 3, 2, 0}; // Khởi tạo mảng a gồm 5 phần tử

SapTuyChon(a, 5, NhoHon); // Ta truyền tên hàm NhoHon vào tham số thứ 3 //Lúc này con trỏhàm p trong hàm SapTuyChon sẽ trỏ vào hàm NhoHon Như vậy câu if trong hàm tương đuong

// if(SoSanhNho(a[j], a[i]) == true) => Hàm đang thực hiện sắp xếp tăng

SapTuyChon(a, 5, LonHon); // Hàm đang thực hiện sắp giảm

Trang 21

// if(SoSanhNho(a[j], a[i]) == true) => Hàm đang thực hiện sắp xếp tăng

SapTuyChon(a, 5, LonHon); // Hàm đang thực hiện sắp giảm

Trang 23

printf("Max = %f", MaxorMin(a,10, LonHon)); // Tìm max và trả về là 69

printf("Max = %f", MaxorMin(a, 10, NhoHon)); //Tìm min và trả về là -13.2

getch();

}

VD3:Thực hiện tính tổng các số nguyên tố, số chính phương, số hoàn thiện

Thử tưởng tượng rằng nếu ta chưa biết đến các tùy biến mã nguồn thì mã nguồn chúng ta sẽ như sau:

Ở đây tôi không dùng template function được lý do là vì số nguyên tố , số hoàn hảo ngoài truyển kiểu

int ra thì truyền kiểu khác sao được ^_< Điều hiển nhiên nhé

bool KiemTraNguyenTo(int x) // Kiểm tra 1 số x có phải là số nguyên tố không

Có nhiều thuật toán để làm bài này

{

if(x < 2)

return false;

else if(x > 2)

Trang 25

bool KiemTraHoanThien(int x) // Hàm kiểm tra 1 số có phải là số hoàn thiện không

// Gio ta phải tạo ra 3 hàm tính tổng

int TongNguyenTo(int a[],int n)

Trang 27

=> Đến đây bạn đã nhận ra rằng tại sao ta lại phải tốn công tạo ra 3 hàm như vậy khi công dụng của chúng đều là tính tổng và chỉ khác biệt đoạn code if

Với ví dụ trên tôi sẽ sử dụng con trỏ hàm để tăng tính tùy biến mã nguồn

Tôi thay 3 hàm tính tổng với chỉ 1 hàm duy nhất là TongTuyChon

int TongTuyChon(int a[], int n, bool (*p)(int))

// Ở hàm main tôi sẽ tùy trường hợp mà truyền vào tham số thứ 3 tên hàm kiểm tra

//để con trỏ hàm p trỏ đến nằm cùng địa chỉ với hàm đó

void main()

{

int a[5] = {1, 3, 5, 12, 6};

printf("Tong nguyen to = %d", TongTuyChon(a, n, KiemTraNguyenTo)); //8

printf("Tong hoan thien = %d", TongTuyChon(a, n, KiemTraHoanThien)); // 6

Trang 28

printf("Tong Chinh phuong = %d", TongTuyChon(a, n, KiemTraChinhPhuong)); /// 5

1 Xây dựng mảng 1 chiều với kiểu dữ liệu " bất kỳ" thực hiện các yêu cầu sau:

Chú ý hàm nào trả về giá trị được thì phải tạo ra hàm trả về giá trị Ko được tạo hàm không kiểu( hàm void)

+ Đếm số dương

+ Đếm số âm

+ Tính tổng số dương

+ Tính tổng số âm

+ Tính tổng các số cực tiểu Số cực tiểu là số lớn nhỏ 2 số xung quang nó (a[i]

<a[i-1] && a[i] < a[i+1])

+ Tính tổng các số cực đại Số cực đại là số lớn hơn 2 số xung quang nó (a[i] 1] && a[i] > a[i+1])

>a[i-+ Xóa các số lớn hơn 100

+ Xóa các số nhỏ hơn 100

Trang 29

15-02-2015 Nguyễn Ái Tuấn

Ngày đăng: 05/06/2015, 11:44

TỪ KHÓA LIÊN QUAN

w