Nguyễn Hồi Danh - 1610391
Lab 9
Câu 1:
b) Chương trình in ra:
L1: “In A(), value = 123”
L2: “In A(int value), value = 246”
L3: “In A(int value), value = 456”
L4: “In A(const A& ob), value = 123”
L5: “In ~A(), value = 123”
L6: “In ~A(), value = 456”
L7: “In ~A(), value = 246”
L8: “In A(int value), value = 789”
L9: “In A(int value), value = 357 “
Các dòng 1,2,3,4,8,9 in ra các giá trị của biến value ứng với các cách gọi hàm tạo đã định
nghĩa.
Riêng với L5,L6 thì vì đối tượng ob2, ob3 ra khỏi tầm vực ( “{ }”) của nó nên hàm hủy sẽ tự
động được gọi nên in ra màn hình như đã định nghĩa trong hàm hủy. Với L7 thì do ta chủ động trả bộ
nhớ cho hệ thống qua câu lệnh “delete ptr1” nên hàm hủy cũng được gọi và xuất ra kết quả như line
7.
c) Hàm ~A(): là hàm hủy, nó được gọi khi đối tượng ra khỏi tầm vực hoặc người dùng chủ
động gọi nó.
d) Nếu xố bỏ dịng “public:”, biên dịch lại chương trình có lỗi vì khi đó các hàm tạo ở trong
tính khả kiến “private” nên trong hàm main ta không được phép truy cập nên sẽ báo lỗi.
e) Nếu thay chữ “private” thành “protected”, biên dịch lại chương trình thì cũng sẽ báo lỗi.
Vì “protected” chỉ được truy cập trong các phương thức thành viên của class đó hoặc các
lớp dẫn xuất của nó mà thơi.
f) Nếu xố bỏ tồn bộ hàm khởi tạo A(). Biên dịch lại chương trình có lỗi. Vì trong trường
hợp này trình biên dịch khơng xác định được hàm khởi tạo mặc định.
g) Nếu xố bỏ tồn bộ hàm khởi tạo A(const A& ob). Biên dịch lại chương trình sẽ khơng có
lỗi vì trong trường hợp này trình biên dịch sẽ tạo ra một hàm tạo mặc định và nó khơng
làm cơng việc như hàm tạo A(const A& ob) đã định nghĩa.
h) Nếu xố bỏ tồn bộ hàm huỷ. Biên dịch lại chương trình khơng có lỗi vì khi đó hệ thống
sẽ tự tạo ra một hàm hủy mặc định khơng làm gì cả, nên sẽ khơng in các câu lệnh trong
hàm hủy:
L5: “In ~A(), value = 123”
L6: “In ~A(), value = 456”
L7: “In ~A(), value = 246”
i) Thay vì khởi động biến m_value trên dịng khởi tạo, như “A():
m_value(123)” ta viết :
“A() {
m_value = 123;
cout << "In A(), value = " << m_value << endl;
}”
Câu 2:
#include <iostream>
#include <iomanip>
using namespace std;
class X {
public:
int m_value;
};
class Y : public X {
public:
int m_value;
};
class Z : public Y {
public:
Z(int vx, int vy, int vz) {
/////////////////////////
X::m_value = vx;
Y::m_value = vy;
this->m_value = vz;
/////////////////////////
}
public:
int m_value;
};
int main() {
Z obj(1, 2, 3);
//(2)
cout <
///////////////////////////
system("pause");
return 0;
};
Câu 3:
a) Chương trình khơng báo lỗi. In ra:
“class X
class Y
class Z
class Z”
b) Nếu thay từ khoá public trong “class Z: public Y” thành protected, biên dịch lại có lỗi. Vì các
thành viên (thuộc tính + phương thức) có tính public của X và Y sẽ đều có tính private trong
ClassZ nên trong hàm main khơng được phép truy cập ở câu lệnh:
“obj.X::display();
obj.Y::display();”
c) Nếu thay từ khoá public trong “class Y: public X” thành protected, biên dịch lại có
lỗi. Vì các thành viên (thuộc tính + phương thức) có tính public của X sẽ có tính protected
trong ClassY. Nên trong hàm main không được phép truy cập ở câu lệnh:
“ obj.X::display();”
d) Nếu thay từ khoá public trong “lớp X” thành protected, biên dịch lại có lỗi. Vì Các thành viên
trong class có thuộc tính private nên khơng được truy cập được trong hàm main với câu
lệnh: “obj.X::display();”
Câu 4:
a) Chương trình in ra:
L1:“Call method via NON-POINTER variable - CASE I:
Type of "this" object is: Class X
Type of "this" object is: Class Y
Type of "this" object is: Class Z
Call method via NON-POINTER variable - CASE II:
Type of "this" object is: Class X
Type of "this" object is: Class X
Type of "this" object is: Class X
Call method via POINTER variable - CASE I:
Type of "this" object is: Class X
Type of "this" object is: Class Y
Type of "this" object is: Class Z
Call method via POINTER variable - CASE II:
Type of "this" object is: Class X
Type of "this" object is: Class X
Type of "this" object is: Class X”
Dòng 2 3 4 thực hiện và in ra nội dung của các hàm display của các class X,Y,Z bình thường
Dịng 6,7,8 in ra nội dung “Type of "this" object is: Class X” vì phép gán x1=y1 thì chỉ nội dung của các
thuộc tính , phương thức mà Y được kế thừa từ X mới gán cho x1 nên khi gọi hàm thì in ra dung
“Type of "this" object is: Class X” mà không phải dung “Type of "this" object is: Class Y” tương tự với
x2=y2, x3=y3.
Dòng 10,11,12 thực hiện và in ra nội dung của các hàm display của các class X,Y,Z bình thường.
X *px1 = new X();
X *px2 = new Y();
X *px3 = new Z();
Các các lệnh này sẽ xin cấp phát vùng nhớ chứa đối tượng kiểu lần lượt là X,Y,Z
nhưng các con trỏ px1,px2,px3 vẫn là kiểu X nên khi gọi hàm display
sẽ hiển thị cùng 1 nội dung “Type of "this" object is: Class X”
b) Thêm từ khóa “virtual” vào thì :
X *px1 = new X();
X *px2 = new Y();
X *px3 = new Z();
Sẽ in ra:
Type of "this" object is: Class X
Type of "this" object is: Class Y
Type of "this" object is: Class Z
Vì Thừa kế ảo (virtual) giúp cho đối tượng của lớp cha (Class X) ở
trên) chỉ được cấp phát một lần.
Câu 5:
a) Thêm vào lớp Y là lớp con của lớp X. Định nghĩa lại (override) phương thức display
trong X, sao cho bên ngồi lớp Y vẫn gọi được – như dịng: “y.display();“ trong hàm main:
class Y : public X {
public:
void display()
{
X::display();
}
};
b) Thêm vào lớp Z là lớp con của lớp Y. Định nghĩa lại (override) phương thức
display thừa kế được từ lớp Y, sao cho bên ngồi lớp Z khơng thể dùng
phương thức display được nữa – như dòng: “z.display();“ trong hàm main:
Cách 1:
class Z : public Y {
private:
void display() {
X::display();
}
};
int main() {
X x;
X y;
Z z;
x.display(); //OK
y.display(); //OK
z.display(); //Error during compilation
system("pause");
return 0;
};
Cách 2:
class Z : public Y {
protected:
void display() {
X::display();
}
};
int main() {
X x;
X y;
Z z;
x.display(); //OK
y.display(); //OK
z.display(); //Error during compilation
system("pause");
return 0;
};
Câu 6:
#include<iostream>
#include<iomanip>
#include<string>
#include<sstream>
using namespace std;
class Date {
public:
int day, month, year;
Date()
{
this->day = 25;
this->month = 2;
this->year = 2017;
}
void tostring()
{
string temp;
if (this->day < 10)
cout << "0" << this->day << "/";
else cout << this->day << "/";
if (this->month<10)
cout << "0" << this->month << "/" << this->year << endl;
else cout << this->month << "/" << this->year << endl;
}
};
Date operator+(Date date) // + : toán tử cin
{
Date date1;
string temp;
getline(cin, temp);
stringstream temp1(temp);
char temp2;
temp1 >> date1.day >> temp2 >> date1.month >> temp2 >> date1.year;
return date1;
}
Date operator++(Date date) // ++: toan tử in ra them số 0
{
string temp;
if (date.day < 10)
cout << "0" << date.day << "/";
else cout << date.day << "/";
if (date.month<10)
cout << "0" << date.month << "/" << date.year << endl;
else cout << date.month << "/" << date.year << endl;
return date;
}
bool operator<(Date date1, Date date2) //<: toan tu so sanh
{
if (date1.year < date2.year)return true;
else if (date1.year > date2.year)return false;
else if (date1.year == date2.year)
{
if (date1.month < date2.month)return true;
else if (date1.month > date2.month)return false;
else if (date1.month == date2.month)
{
if (date1.day < date2.month)return true;
else return false;
}
}
}
int main()
{
Date d1, d2;
cout << "Enter date:";
d1=+d1;
cout << "Enter date:";
d2=+d2;
++ d1;
++ d2;
cout << (d1 < d2 ? "d1<d2" : "d1>=d2") << endl;
Date d3;
d3.tostring() ;
system("pause");
return 0;
}