25/05/2018, 12:44

Nói thêm về kiểu phương thức và kiểu đối của phương thức

Phương thức có thể không có giá trị trả về (kiểu void) hoặc có thể trả về một giá trị có kiểu bất kỳ, kể cả giá trị kiểu đối tượng, con trỏ đối tượng, tham chiếu đối tượng. Đối của phương thức (cũng giống như đối ...

Phương thức có thể không có giá trị trả về (kiểu void) hoặc có thể trả về một giá trị có kiểu bất kỳ, kể cả giá trị kiểu đối tượng, con trỏ đối tượng, tham chiếu đối tượng.

Đối của phương thức (cũng giống như đối của hàm) có thể có kiểu bất kỳ:

+ Kiểu dữ liệu chuẩn như int, float, char,... . Con trỏ hoặc tham chiếu đến kiểu dữ liệu chuẩn như int*, float*, char*, int&, float&, char&,...

+ Các kiểu ngoài chuẩn đã định nghĩa trước như đối tượng, cấu trúc, hợp, enum,... . Con trỏ hoặc tham chiếu đến các kiểu ngoài chuẩn này.

+ Kiểu đối tượng của chính phương thức, con trỏ hoặc tham chiếu đến kiểu đối tượng này.

+ Thuộc tính (thành phần dữ liệu) của lớp có thể là đối tượng của lớp khác đã định nghĩa bên trên.

+ Phương thức có giá trị trả về kiểu đối tượng và con trỏ đối tượng.

Nội dung chương trình là nhập một dẫy hình chữ nhật, sau đó tìm hình chữ nhật có max diện tích và hình chữ nhật có max chu vi.

Chương trình được tổ chức thành 2 lớp:

+ Lớp HINH_CN gồm:

- Các thuộc tính: d và r (chiều dài và chiều rộng)

- Các phương thức

void nhapsl() ; // Nhập chiều dài, rộng

int dien_tich(); // Tính diện tích

int chu_vi() ; // Tính chu vi

+ Lớp DAY_HINH_CN gồm

- Các thuộc tính:

int n ; //số hình chữ nhật của dẫy

HINH_CN *h; //Con trỏ tới dẫy đối tượng của lớp HINH_CN

- Các phương thức

void nhapsl(); // Nhập một dẫy hình chữ nhật

HINH_CN hinh_dt_max() ; //Trả về hình chữ nhật có 

// diện tích max

HINH_CN *hinh_cv_max() ; // Trả về con trỏ tới HCN có 

// chu vi max

#include <conio.h>

#include <iostream.h>

class HINH_CN

{

private:

int d, r; // chieu dai va chieu rong

public:

void nhapsl()

{

cout << " 
Nhap chieu dai va chieu rong: " ;

cin >> d >> r ;

}

void in()

{

cout << "
chieu dai = " << d ;

cout << " chieu rong= " << r;

}

int dien_tich()

{

return d*r;

}

int chu_vi()

{

return 2*(d+r);

}

} ;

class DAY_HINH_CN

{

private:

int n; // So hinh ch nhat

HINH_CN *h;

public:

void nhapsl();

HINH_CN hinh_dt_max() ;

HINH_CN *hinh_cv_max() ;

} ;

void DAY_HINH_CN::nhapsl()

{

cout << "So hinh CN = " ;

cin >> n;

h = new HINH_CN[n+1];

for (int i=1;i<=n;++i)

h[i].nhapsl();

}

HINH_CN DAY_HINH_CN::hinh_dt_max()

{

HINH_CN hdtmax;

hdtmax = h[1];

for (int i=2; i<=n; ++i)

if (h[i].dien_tich() > hdtmax.dien_tich() )

hdtmax = h[i];

return hdtmax;

}

HINH_CN *DAY_HINH_CN::hinh_cv_max()

{

int imax = 1;

for (int i=2; i<=n; ++i)

if (h[i].chu_vi() > h[imax].chu_vi() )

imax = i ;

return (h+imax);

}

void main()

{

DAY_HINH_CN d;

HINH_CN hdtmax;

d.nhapsl();

hdtmax = d.hinh_dt_max();

hdtmax.in() ;

HINH_CN *hcvmax=d.hinh_cv_max();

hcvmax->in() ;

getch();

}

+ Thuộc tính (thành phần dữ liệu) của lớp có thể là đối tượng của lớp khác đã định nghĩa bên trên.

+ Phương thức có giá trị trả về kiểu đối tượng

+ Vai trò của con trỏ this (xem phương thức maxdt của lớp TAM_GIAC)

+ Phương thức tĩnh (xem phương thức tao_tg của lớp TAM_GIAC)

Nội dung chương trình là nhập một dẫy các điểm, sau đó tìm tam giác lớn nhất (về diện tích) có đỉnh là các điểm vừa nhập.

Chương trình được tổ chức thành 2 lớp:

+ Lớp DIEM gồm:

- Các thuộc tính: x và y (toạ độ của điểm)

- Các phương thức

void nhapsl() ; // Nhập x, y

void in() ; // In toạ độ   

double do_dai(DIEM d2) ; // Tính độ dài đoạn thẳng qua 

// 2 điểm (điểm ẩn xác định bởi this và điểm d2)

+ Lớp TAM_GIAC gồm:

- Các thuộc tính:

DIEM d1,d2,d3; // 3 đỉnh của tam giác

- Các phương thức:

void nhapsl(); // Nhập toạ độ 3 đỉnh

void in(); // In toạ độ 3 đỉnh

// Tạo một đối tượng TAM_GIAC từ 3 đối tượng DIEM

static TAM_GIAC tao_tg(DIEM e1, DIEM e2, DIEM e3)

double dien_tich() ; // Tính diện tích 

// Tìm tam giác có diện tích max trong 2 tam giác *this và t2

TAM_GIAC maxdt(TAM_GIAC t2); 

+ Các vấn đề đáng chú ý trong chương trình là:

- Phương thưc tĩnh tao_tg (sẽ giải thích bên dưới)

- Phương thưc maxdt

+ Thuật toán là:

- Duyệt qua các tổ hợp 3 điểm.

- Dùng phương thức tao_tg để lập tam giác từ 3 điểm

- Dùng phương thức maxdt để chọn tam giác có diện tích lớn hơn trong 2 tam giác: tam giác vừa tạo và tam giác có diện tích max (trong số các tam giác đã tạo)

#include <conio.h>

#include <iostream.h>

#include <math.h>

class DIEM

{

private:

double x,y; // Toa do cua diem

public:

void nhapsl()

{

cout << " Toa do x, y: " ;

cin >> x >> y ;

}

void in()

{

cout << " x = " << x << " y = " << y;

}

double do_dai(DIEM d2)

{

return sqrt(pow(x-d2.x,2) + pow(y-d2.y,2) );

}

} ;

class TAM_GIAC

{

private:

DIEM d1,d2,d3; // 3 dinh tam giac

public:

void nhapsl();

void in();

static TAM_GIAC tao_tg(DIEM e1, DIEM e2, DIEM e3)

{

TAM_GIAC t;

t.d1=e1; t.d2 = e2; t.d3=e3;

return t;

}

double dien_tich() ;

TAM_GIAC maxdt(TAM_GIAC t2);

} ;

void TAM_GIAC::nhapsl()

{

cout << "
Dinh 1 - " ;

d1.nhapsl();

cout << "
Dinh 2 - " ;

d2.nhapsl();

cout << "
Dinh 3 - " ;

d3.nhapsl();

}

void TAM_GIAC::in()

{

cout << "
Dinh 1: " ; d1.in();

cout << "
Dinh 2: " ; d2.in();

cout << "
Dinh 3: " ; d3.in();

}

double TAM_GIAC::dien_tich()

{

double a,b,c,p,s;

a=d1.do_dai(d2);

b=d2.do_dai(d3);

c=d3.do_dai(d1);

p=(a+b+c)/2;

return sqrt(p*(p-a)*(p-b)*(p-c));

}

TAM_GIAC TAM_GIAC::maxdt(TAM_GIAC t2)

{

if (this->dien_tich() > t2.dien_tich())

return *this ;

else

return t2;

}

void main()

{

DIEM d[50];

int n, i ;

clrscr();

cout << "
 So diem= ";

cin >> n;

for (i=1; i<=n; ++i)

{

cout << "
Nhap diem " << i << " - " ;

d[i].nhapsl();

}

int j, k ;

TAM_GIAC tmax, t;

tmax = TAM_GIAC::tao_tg(d[1],d[2],d[3]);

for (i=1;i<=n-2;++i)

for (j=i+1;j<=n-1;++j)

for (k=j+1;k<=n;++k)

{

t=TAM_GIAC::tao_tg(d[i],d[j],d[k]);

tmax = tmax.maxdt(t);

}

cout << "

Tam giac co dien tich lon nhat: " ;

tmax.in();

cout << "
Dien tich = " << tmax.dien_tich();

getch();

}

Để tạo một đối tượng TAM_GIAC từ 3 đối tượng DIEM ta đã dùng phương thức tĩnh:

static TAM_GIAC tao_tg(DIEM e1, DIEM e2, DIEM e3)

{

TAM_GIAC t;

t.d1=e1; t.d2 = e2; t.d3=e3;

return t;

}
Phương thức tĩnh (sẽ nói thêm trong các mục bên dưới) có các đặc điểm sau:

+ Nó giống phương thức thông thường ở chỗ: Trong thân của nó có thể truy nhập tới các thành phần của lớp (cụ thể là lớp TAM_GIAC).

+ Nó khác phương thức thông thường ở chỗ:

- Không có đối ngầm định xác định bởi con trỏ this (như phương thức thông thường). Như vậy phương thức tao_tg có đúng 3 đối.

- Nó không gắn với một đối tượng cụ thể nào của lớp, nên trong lời gọi tới phương thức ảo có thể dùng tên lớp, ví dụ (xem hàm main):

t=TAM_GIAC::tao_tg(d[i],d[j],d[k]);
Không thể thay phương thức tĩnh tao_tg bằng hàm, vì trong thân hàm không được truy xuất đến các thuộc tính của lớp TAM_GIAC. Tuy nhiên có một giải pháp khác là dùng khái niệm hàm bạn (friend). Hàm bạn của một lớp có quyền truy nhập đến các thuộc tính của lớp. Trong ví dụ 3 dưới đây ta sẽ xây dựng hàm tao_tg như một hàm bạn của lớp TAM_GIAC. Còn một giải pháp nữa là dùng hàm tạo (constructor) sẽ trình bầy trong các chương sau:

Chương trình dưới đây có nội dung giống như ví dụ 2, nhưng thay phương thức tĩnh tao_tg bằng hàm bạn tao_tg.

Minh hoạ cách dùng hàm bạn. Nội dung chương trình giống như trong ví dụ 2.

#include <conio.h>

#include <iostream.h>

#include <math.h>

class DIEM

{

private:

double x,y; // Toa do cua diem

public:

void nhapsl()

{

cout << " Toa do x, y: " ;

cin >> x >> y ;

}

void in()

{

cout << " x = " << x << " y = " << y;

}

double do_dai(DIEM d2)

{

return sqrt(pow(x-d2.x,2) + pow(y-d2.y,2) );

}

} ;

class TAM_GIAC

{

private:

DIEM d1,d2,d3; // 3 dinh tam giac

public:

void nhapsl();

void in();

friend TAM_GIAC tao_tg(DIEM e1, DIEM e2, DIEM e3)

{

TAM_GIAC t;

t.d1=e1; t.d2 = e2; t.d3=e3;

return t;

}

double dien_tich() ;

TAM_GIAC maxdt(TAM_GIAC t2);

} ;

void TAM_GIAC::nhapsl()

{

cout << "
Dinh 1 - " ;

d1.nhapsl();

cout << "
Dinh 2 - " ;

d2.nhapsl();

cout << "
Dinh 3 - " ;

d3.nhapsl();

}

void TAM_GIAC::in()

{

cout << "
Dinh 1: " ; d1.in();

cout << "
Dinh 2: " ; d2.in();

cout << "
Dinh 3: " ; d3.in();

}

double TAM_GIAC::dien_tich()

{

double a,b,c,p,s;

a=d1.do_dai(d2);

b=d2.do_dai(d3);

c=d3.do_dai(d1);

p=(a+b+c)/2;

return sqrt(p*(p-a)*(p-b)*(p-c));

}

TAM_GIAC TAM_GIAC::maxdt(TAM_GIAC t2)

{

if (this->dien_tich() > t2.dien_tich())

return *this ;

else

return t2;

}

void main()

{

DIEM d[50];

int n, i ;

clrscr();

cout << "
 So diem= ";

cin >> n;

for (i=1; i<=n; ++i)

{

cout << "
Nhap diem " << i << " - " ;

d[i].nhapsl();

}

int j, k ;

TAM_GIAC tmax, t;

tmax = tao_tg(d[1],d[2],d[3]);

for (i=1;i<=n-2;++i)

for (j=i+1;j<=n-1;++j)

for (k=j+1;k<=n;++k)

{

t=tao_tg(d[i],d[j],d[k]);

tmax = tmax.maxdt(t);

}

cout << "

Tam giac co dien tich lon nhat: " ;

tmax.in();

cout << "
Dien tich = " << tmax.dien_tich();

getch();

}
Hàm bạn có thể xây dựng bên trong định nghĩa lớp (như chương trình trên) hoặc có thể khai báo bên trong và xây dựng bên ngoài định nghĩa lớp như sau:

class TAM_GIAC

{

private:

DIEM d1,d2,d3; // 3 dinh tam giac

public:

void nhapsl();

void in();

friend TAM_GIAC tao_tg(DIEM e1,DIEM e2,DIEM e3);

double dien_tich() ;

TAM_GIAC maxdt(TAM_GIAC t2);

} ;

TAM_GIAC tao_tg(DIEM e1, DIEM e2, DIEM e3)

{

TAM_GIAC t;

t.d1=e1; t.d2 = e2; t.d3=e3;

return t;

}

Nhận xét: Không cho phép dùng từ khoá friend khi xây dựng hàm (bên ngoài lớp)

0