Tải bản đầy đủ (.pdf) (29 trang)

Lớp đối tượng và tính đóng gói - Nội tuyến tự động (in-line)

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (58.94 KB, 29 trang )

Chương 2
Lớp
, Đ
ối tượng và tính đóng gói



38
38
Bài tập III


1. Viết chương trình thay đổi lớp stack để cho nó cấp phát bộ nhớ động cho ngăn xếp
chứa các ký tự. Kích thước ngăn xếp được chỉ rõ bằng một tham số với hàm tạo.
Hàm hủy giải phóng bộ nhớ động.

2. Hãy tạo lớp
t_and_d
để truyền ngày và giờ hệ thống hiện hành như một tham số
cho hàm tạo của nó khi được tạo ra. Lớp gồm có hàm thành viên hiển thò ngày giờ
này lên màn hình. Dùng các hàm ngày và giờ chuẩn trong thư viện chuẩn để tìm và
hiện thò ngày.

3. Viết chương trình tạo lớp box có hàm tạo được truyền 3 giá trò double, diễn tả độ
dài các cạnh của hộp. Hãy cho lớp box tính thể tích của hình lập phương và lưu trữ
kết qủa trong biến double. Tạo hàm thành viên vol() để hiển thò thể tích của mỗi đối
tượng box.



IV/ Nội tuyến tự động (in-line)



1/ Khái niệm
Khi đònh nghiã hàm thành phần là đủ ngắn thì có thể đặt đònh nghiã trong khai báo
hàm trong lớp đó. Hàm này sẽ được gọi là
hàm nội tuyến
(in-line func.) và không
cần dùng từ khoá inline đứng trước hàm đó.

Ví dụ 4.1
#include <iostream.h>

class samp {
int i, j;
public:
samp(int a, int b);

// divisible() is defined here and automatically in-lined

int divisible() { return !(i%j) ; }
};
Chương 2
Lớp
, Đ
ối tượng và tính đóng gói



39
39
samp::samp(int a, int b)

{
i = a;
j = b;
}

int main()
{
samp ob1(10, 2), ob2(10, 3);

// this is true
if(ob1.divisible()) cout << "10 divisible by 2\n";

// this is false
if(ob2.divisible()) cout << "10 divisible by 3\n";

return 0;
}

Ví dụ 4.2
Dùng hàm nội tuyến để đònh nghiã các hàm tạo và hàm hủy
#include <iostream.h>

class samp {
int i, j;
public:

samp(int a, int b) { i = a; j = b; }
// inline constructor
int divisible() { return !(i%j); }
};



Ví dụ 4.3
Một hàm ngắn ở bên trong một khai báo lớp
cho dù đặc điểm nội tuyến tự động là không có giá trò.

class myclass {
int i;
public:
myclass(int n) { i = n; }
Chương 2
Lớp
, Đ
ối tượng và tính đóng gói



40
40
void show() { cout << i; }
};


Bài tập IV


1. Viết chương trình chuyển đổi lớp stack trong ví dụ 2.3 chương 2, để lớp này sử
dụng các hàm nội tuyến tự động ở những nơi thích hợp.

2. Viết chương trình chuyển đổi lớp strtype trong ví dụ 2.4 chương 2, để lớp này sử

dụng các hàm nội tuyến tự động.


V/ Gán đối tượng

1/ Khái niệm
Một đối tượng được gán cho một đối tượng khác để cả hai đối tượng có cùng kiểu,
khi đó
sự sao chép từng bit của các thành viên dữ liệu được thực hiện
.

Ví dụ 5.1
// An example of object assignment.
#include <iostream.h>

class myclass {
int a, b;
public:
void set(int i, int j) { a = i; b = j; }
void show() { cout << a << ' ' << b << "\n"; }
};

int main()
{
myclass o1, o2;
o1.set(10, 4);

// assign o1 to o2
Chương 2
Lớp

, Đ
ối tượng và tính đóng gói



41
41

o2 = o1
;

o1.show();
o2.show();
return 0;
}

Nếu bổ sung các dòng lệnh sau đây vào trước dòng return 0; , kết quả sẽ ra sao ?
o1.set(3, 2);
o1.show();
o2.show();


2/ Các tính chất
a/ Lệnh gán đối tượng chỉ
áp dụng cho các đối tượng có cùng kiểu
(về mặt vật lý) và
cùng tên kiểu
.

Ví dụ 5.2

// This program has an error.
#include <iostream.h>

class
myclass
{
int a, b;
public:
void set(int i, int j) { a = i; b = j; }
void show() { cout << a << ' ' << b << "\n"; }
};

/* This class is similar to myclass but uses a different class name and thus appears
as
a different type to the compiler */
class
yourclass
{
int a, b;
public:
void set(int i, int j) { a = i; b = j; }
void show() { cout << a << ' ' << b << "\n"; }
};
Chương 2
Lớp
, Đ
ối tượng và tính đóng gói




42
42
int main()
{
myclass o1;
yourclass o2;

o1.set(10, 4);

o2 = o1
; // ERROR, objects not of same type name

o1.show();
o2.show();
return 0;
}

b/ Phép gán đối tượng còn áp dụng cho các dữ liệu phức tạp như mảng, ...

Ví dụ 5.3
#include <iostream.h>

#define SIZE 10

// Declare a stack class for characters.
class stack {
char stck[SIZE]; // holds the stack
int tos; // index of top-of-stack
public:
stack(); // constructor

void push(char ch); // push character on stack
char pop(); // pop character from stack
};

// Initialize the stack.
stack::stack()
{
cout << "Constructing a stack\n";
tos = 0;
}

Chửụng 2
Lụựp
, ẹ
oỏi tửụùng vaứ tớnh ủoựng goựi



43
43
// Push a character.
void stack::push(char ch)
{
if(tos==SIZE) {
cout << "Stack is full\n";
return;
}
stck[tos] = ch;
tos++;
}


// Pop a character.
char stack::pop()
{
if(tos==0) {
cout << "Stack is empty\n";
return 0; // return null on empty stack
}
tos--;
return stck[tos];
}

int main()
{
// Create two stacks that are automatically initialized.
stack s1, s2;
int i;

s1.push('a');
s1.push('b');
s1.push('c');

// clone s1

s2 = s1
; // now s1 and s2 are identical

for(i=0; i<3; i++) cout << "Pop s1: " << s1.pop() << "\n";
for(i=0; i<3; i++) cout << "Pop s2: " << s2.pop() << "\n";
Chương 2

Lớp
, Đ
ối tượng và tính đóng gói



44
44
return 0;
}


c/ Đối với các
đối tượng có sử dụng chuổi
, khi thực hiện phép gán đối tượng phải
chắc chắn rằng không hủy bỏ các thông tin cần thiết trong đối tượng đó.

Ví dụ 5.4
// This program contains an error.

#include <iostream.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>

class strtype {
char *p;
int len;
public:
strtype(char *ptr);

~strtype();
void show();
};
strtype::strtype(char *ptr)
{
len = strlen(ptr);
p = (char *) malloc(len+1);
if(!p) {
cout << "Allocation error\n";
exit(1);
}
strcpy(p, ptr);
}

strtype::~strtype()
{
cout << "Freeing p\n";
Chương 2
Lớp
, Đ
ối tượng và tính đóng gói



45
45
free(p);
}

void strtype::show()

{
cout << p << " - length: " << len;
cout << "\n";
}

int main()
{
strtype s1("This is a test."), s2("I like C++.");

s1.show();
s2.show();

// assign s1 to s2 - - this generates an error

s2 = s1;

s1.show();
s2.show();
return 0;
}
Nguyên nhân nào gây ra lỗi ?

Bài tập V


1. Tìm lỗi sai trong đoạn chương trình sau
#include <iostream>
class cl1 {
int i, j;
public:

cl1(int a, int b) { i = a; j = b; }
// ...
};
class cl2 {
Chương 2
Lớp
, Đ
ối tượng và tính đóng gói



46
46
int i, j;
public:
cl2(int a, int b) { i = a; j = b; }
// ...
};

int main()
{
cl1 x(10, 20);
cl2 y(0, 0);
x = y;

// ...
}

2. Viết chương trình dựa vào lớp queue trong bài tập II/ 1. chương II chứng tỏ một
hàng đợi có thể được gán cho một hàng đợi khác.


3. Nếu lớp queue trong câu 2. cấp phát bộ nhớ động để giữ hàng đợi, tại sao trong
trường hợp này, một hàng đợi không thể được gán cho hàng đợi khác.


VI/ Truyền các đối tượng sang hàm

1/ Việc truyền các đối tượng cho hàm giống như truyền các đối số thông thường.
Tham số của hàm có kiểu dữ liệu là kiểu lớp, và
đối số truyền cho hàm chính là đối
tượng
.

Giống như các kiểu dữ liệu khác, theo ngầm đònh, tất cả các đối tượng được truyền
bởi giá trò cho một hàm.

Ví dụ 6.1
Truyền một đối tượng cho hàm.
#include <iostream.h>

class samp {
int i;
public:
Chương 2
Lớp
, Đ
ối tượng và tính đóng gói




47
47
samp(int n) { i = n; }
int get_i() { return i; }
};

// Return square of o.i.
int sqr_it(
samp o
)
{
return o.get_i() * o.get_i();
}

int main()
{
samp a(10), b(2);

cout << sqr_it(
a
) << "\n";
cout << sqr_it(
b
) << "\n";

return 0;
}

2/ Do đối tượng được truyền bởi giá trò cho một hàm, có nghóa là việc sao chép từng
bit của đối số được thực hiện và chính sao chép này được sử dụng bởi hàm. Do đó,

những thay đổi cho đối tượng bên trong hàm không có ảnh hưởng đến sự gọi đối
tượng.

Ví dụ 6.2
#include <iostream.h>

class samp {
int i;
public:
samp(int n) { i = n; }
void set_i(int n) { i = n; }
int get_i() { return i; }
};

// Set o.i to its square. This has no effect on the object used to call sqr_it(),
Chương 2
Lớp
, Đ
ối tượng và tính đóng gói



48
48
however.
void sqr_it(
samp o
)
{
o.set_i( o.get_i() * o.get_i() ) ;


cout << "Copy of a has i value of " << o.get_i();
cout << "\n";
}

int main()
{
samp a(10);

sqr_it(
a
) ; // a passed by value, displays 100

cout << "But, a.i is unchanged in main: ";
cout << a.get_i(); // displays 10
return 0;
}


3/ Khi truyền điạ chỉ của đối tượng sang hàm (sẽ không tạo ra bản sao đối tượng),
nội dung của đối tượng sẽ bò thay đổi.

Ví dụ 6.3
#include <iostream.h>
class samp {
int i;
public:
samp(int n) { i = n; }
void set_i(int n) { i = n; }
int get_i() { return i; }

};

/* Set o.i to its square. This affects the calling argument. */
void sqr_it(
samp *o
)
{

×