Các hàm được định nghĩa hợp lệ trong một lớp được gọi là các phương thức Method và chúng là các hàm duy nhất có thể xử lý dữ liệu của các đối tượng của lớp đó.. Thành phần dữ liệu data m
Trang 1CÂU HỎI LÝ THUYẾT
Câu 1: Trình bày khái niệm về đối tượng (object), lớp (class), thể hiện (instance),
thành phần dữ liệu (data member), phương thức (method), thông điệp (message).
Trả lời:
Một lớp là một bản mẫu mô tả các thông tin cấu trúc dữ liệu, lẫn các thao tác
hợp lệ của các phần tử dữ liệu Khi một phần tử dữ liệu được khai báo là phần tử của
một lớp thì nó được gọi là một đối tượng (Object) Các hàm được định nghĩa hợp lệ trong một lớp được gọi là các phương thức (Method) và chúng là các hàm duy nhất
có thể xử lý dữ liệu của các đối tượng của lớp đó Một thể hiện (Instance) là một vật
thể có thực bên trong bộ nhớ, thực chất đó là một đối tượng (nghĩa là một đối tượng được cấp phát vùng nhớ)
Thành phần dữ liệu (data member) hay còn gọi là dữ liệu thành viên của lớp là
các dữ liệu thể hiện các thuộc tính đặc trưng của một lớp Các phương thức định nghĩa trong một lớp có thể được gọi bởi các đối tượng của lớp đó Điều này được gọi
là gửi một thông điệp (Message) cho đối tượng Các thông điệp này phụ thuộc vào
đối tượng, chỉ đối tượng nào nhận thông điệp mới phải làm việc theo thông điệp đó Các đối tượng đều độc lập với nhau vì vậy các thay đổi trên các biến thể hiện của đối tượng này không ảnh hưởng gì trên các biến thể hiện của các đối tượng khác và việc gửi thông điệp cho một đối tượng này không ảnh hưởng gì đến các đối tượng khác
Câu 2: Trình bày các toán tử xác định phạm vi lớp và truy cập tới các thành viên Ví
dụ minh hoạ?
Trả lời:
Toán tử định phạm vi “::” được dùng trong các định nghĩa hàm của các phương
thức trong các lớp, để khai báo lớp chủ của các phương thức đang được định nghĩa
đó Toán tử định phạm vi còn có thể được dùng để phân biệt các thành phần trùng tên của các lớp cơ sở khác nhau
Các toán tử được sử dụng để truy cập các thành viên của lớp được đồng nhất với các toán tử sử dụng để truy cập các thành viên của cấu trúc Toán tử lựa chọn thành
viên dấu chấm (.) được kết hợp với một tên của đối tượng hay với một tham chiếu tới
một đối tượng để truy cập các thành viên của đối tượng Toán tử lựa chọn thành viên
Trang 2mũi tên (->)được kết hợp với một con trỏ trỏ tới một truy cập để truy cập các thành
viên của đối tượng
VD:
#include <iostream>
using namespace std;
class connguoi
{
public:
string hoten;
int tuoi;
public:
void set();
};
void connguoi :: set()
{
cout << "Nhap Ho Ten: ";
fflush(stdin); // Xóa bộ đệm
getline(cin, this->hoten);
cout << "Nhap Tuoi: ";
cin >> this->tuoi;
}
int main()
{
connguoi obj; // Khai báo obj là 1 đối tượng trong lớp connguoi
obj.set();
cout << "Ho Ten: " << obj.hoten << endl;
cout << "Tuoi: " << obj.tuoi << endl;
return 0;
}
Phạm vi truy cập là cách mà người lập trình quy định về quyền được truy xuất
đến các thành phần của lớp
Trong C++ có 3 loại phạm vi chính là: private, protected, public
public: Không hạn chế Thành phần có thuộc tính này có thể được truy
cập ở bất kì vị trí nào
private: Thành phần có thuộc tính này sẽ chỉ được truy cập từ bên trong
lớp Bên ngoài lớp hay trong lớp dẫn xuất sẽ không thể truy cập được
protected: Mở rộng hơn private một chút Thành phần có thuộc tính này
sẽ có thể truy cập ở trong nội bộ lớp và trong lớp dẫn xuất
Trang 3Câu 3: Trình bày khái niệm về hàm khởi tạo, hàm huỷ, các tính chất Ví dụ minh
hoạ?
Trả lời:
Hàm khởi tạo là một hàm thành viên đặc biệt của một lớp Nó sẽ được tự động
gọi đến khi một đối tượng của lớp đó được khởi tạo
Một hàm tạo sẽ khác những hàm thông thường ở những điểm sau:
Có tên trùng với tên lớp
Không có kiểu dữ liệu trả về ( kể cả kiểu void)
Tự động được gọi khi một đối tượng thuộc lớp được tạo ra
Nếu chúng ta không khai báo một hàm tạo, trình biên dịch C++ sẽ tự động tạo một hàm tạo mặc định cho chúng ta (sẽ là hàm không có tham số nào và
có phần thân trống)
Hàm khởi tạo về cơ bản sẽ được chia làm 3 loại:
1 Hàm khởi tạo không tham số
2 Hàm khởi tạo có tham số
VD1:
class sinhvien
{
private:
string ten;
int tuoi;
public:
sinhvien() //ham khoi tao khong co tham so
{
this->ten = "";
this->tuoi = 0;
}
sinhvien(string ten, int tuoi) // ham tao co tham so
{
this->ten = ten;
this->tuoi = tuoi;
}
};
3 Hàm khởi tạo sao chép: Khi nào cần dùng hàm tạo sao chép?: Khi trong
lớp có thuộc tính con trỏ hoặc tham chiếu
VD2:
Class DT
{
private:
int n; //Bac cua da thuc
Trang 4double *a;
public:
DT u;
DT v(u); //Khi đó hai con tro * u.a và v.a cùng tro * đế/ n một vùng nhớ.
};
DT::DT(const DT &d)
{
this->n = d.n;
this->a = new double[d.n+1];
for (int i=0;i<=d.n;++i) this->a[i] = d.a[i];
}
Hàm huỷ cũng là một hàm thành viên đặc biệt giống như hàm tạo, được dùng
để hủy bỏ, giải phóng các đối tượng khi nó hết phạm vi tồn tại
Hàm hủy:
- Không có đối số
- Không có giá trị trả về
- Không định nghĩa lại
- Trùng tên với lớp và có dấu ~ ở trước
- Thực hiện một số công việ trước khi hệ thống giải phóng bộ nhớ
- Chương trình dich tư động sinh hàm hủy mặc định
VD3:
public:
~DT() { this->n=0;
delete this->a;
}
Câu 4: Trình bày khái niệm về nạp chồng toán tử, cho ví dụ minh hoạ?
Trả lời:
Nạp chồng toán tử (Operator Overloading) được dùng để định nghĩa toán tử
cho có sẵn trong c++ phục vụ cho dữ liệu riêng do người dùng tạo ra
Các toán tử: *, / , +, -, <<, >>, …
VD: Xây dựng lớp phân số Nạp chồng toán tử + để cộng hai phân số
class phanso
{
int ts,ms;
Trang 5phanso operator +(phanso p);
};
phanso phanso::operator+(phanso p)
{
phanso kq;
kq.ts=ts*p.ms+ms*p.ts;
kq.ms=ms*p.ms;
return kq;
}
Câu 5: Trình bày khái niệm về các thành viên tĩnh (static) của lớp, cho VD minh
hoạ?
Trả lời:
Khi khai báo một thành viên là static, khi đó chỉ có một địa chỉ ô nhớ được truy cập Khi khởi tạo một đối tượng, thành phần static sẽ được lưu giá trị của đối tượng trước đó Các thành viên static được truy cập thông qua tên lớp Các biến static đôi
khi được gọi là class variables, class fields, hoặc class-wide fields bởi vì chúng
không phải là biến của đối tượng mà tồn tại theo lớp
VD:
// Lop HDBH (hoa don ban hang)
#include <conio.h>
#include <iostream>
using namspace std;
class HDBH
{
private:
int shd ;
char *tenhang ;
double tienban ;
static int tshd ;
static double tstienban ;
public:
static void in()
{
cout <<"\n" << tshd;
cout <<"\n" << tstienban;
}
};
int HDBH::tshd=5;
double HDBH::tstienban=20000.0;
void main()
{
HDBH::in();
Trang 6}
Kết quả:
5
20000
Câu 6: Khái niệm về tính kế thừa, tính chất Nêu ví dụ minh hoạ?
Trả lời:
• Kế thừa là khả năng cho phép xây dựng một lớp mới:
▫ Được thừa hưởng các thành phần từ một hay nhiều lớp đã có (lớp cơ sở)
▫ Trong lớp ta có thể bổ sung thêm các thành phần hoặc định nghĩa lại các thành phần
• Đặc tính của kế thừa
– Cho phép định nghĩa lớp mới từ lớp đã có, khi đó:
Lớp mới được gọi là lớp con (subclass) hay lớp dẫn xuất (derived class).
Lớp ban đầu gọi là lớp cha (superclass) hay lớp cơ sở (base class).
– Nhiều lớp có thể dẫn xuất từ một lớp cha
– Một lớp có thể là dẫn xuất của nhiều lớp cha
VD:
• Xây dựng ba lớp sau:
▫ Lớp người
▫ Lớp SinhVien
▫ Lớp GiaoVien
Nguoi
DL: hs, ns, gt
PT:nhap(),
GV
DL: ht, ns, gt PT:nhap(), in(),
SV
DL: ht, ns, gt PT:nhap(),in() ,
xeploai()
Trang 7Câu 7: Tính đa hình, các đặc trưng của phương thức ảo, ví dụ minh hoạ?.
Trả lời:
Đa hình là khả năng cho phép:
• Cho phép các lớp được định nghĩa các phương thức trùng nhau: cùng tên, cùng số lượng và kiểu tham số, cùng kiểu trả về Việc định nghĩa phương thức trùng nhau của các lớp kế thừa nhau còn được gọi là sự nạp chồng phương thức
• Khi gọi các phương thức trùng tên, dựa vào đối tượng đang gọi mà chương trình sẽ thực hiện phương thức của lớp tương ứng, và do đó, sẽ cho các kết quả khác nhau
• Ví dụ: Xây dựng lớp người, lớp sinh viên, lớp giáo viên cùng có phương thức Nhap() và phương thức Xuat()
Như vậy đa hình là khả năng cho phép viết chương trình để xử lý tổng quát các đối tượng của tất cả các lớp trong một phân cấp như các đối tượng của lớp cơ sở Do vậy một thông điệp được gửi đi mà không cần biết đối tượng nhận thuộc lớp nào
Để cài đặt phương thức có tính đa hình ta dùng phương thức ảo và phương thức thuần ảo
Phương thức ảo là phương thức được định nghĩa ở lớp cơ sở (lớp cha) mà các
lớp dẫn xuất (lớp con) muốn sử dụng phải định nghĩa lại Dùng từ khoá virtual để
khai báo phương thức ảo:
Cú pháp:
virtual <kiế*u tra * vếC > <tến phương thức >(<d/s tham số/ >)
{
… …
}
Phương thức khởi tạo không được là phương thức ảo nhưng phương thức hủy bỏ
có thể là phương thức ảo
Đặc trưng của phương thức ảo.
• Phương thức ảo không thể là các phương thức tĩnh
• Một phương thức ảo có thể được khai báo là friend trong một lớp khác nhưng các hàm friend của lớp thì không thể là phương thức ảo.
Trang 8• Không cần thiết phải ghi rõ từ khóa virtual trước định nghĩa một
phương thức ảo trong lớp dẫn xuất
• Khi một phương thức được định nghĩa là ảo, từ lớp cơ sở đến lớp dẫn xuất đều phải định nghĩa thống nhất về tên, kiểu trả về và danh sách các tham số Nếu
ta sơ xuất định nghĩa phương thức khác đi thì trình biên dịch sẽ hiểu đó là phương thức khác
VD:
#include <iostream>
class A
{
public:
virtual void Chao() //phuong thuc ao
{
cout<<"\nA chao cac ban";
}
};
class B:public A
{
public:
void Chao()
cout<<"\nB chao cac ban";
} };
class C:public A
{
public:
void Chao() {
cout<<"\nC chao cac ban";
} };
void main()
{
A a;
A *pa= new A; pa->Chao(); //goi chao cua A
B b;
pa=&b; pa->Chao(); //goi chao cua B
C c;
pa=&c; pa->Chao(); //goi chao cua C
}
Nhận xét:
- Phương thức Chao() có tính đa hình: cùng lời gọi pa->chao() nhưng lần 1 gọi chao cua A, lan 2 gọi chao cua B, lan 3 goi chao cua C
Trang 9- Nếu trong lớp B, C không định nghĩa lại phương thức chào thì cả ba lần đều gọi chào của A
- Nếu phương thức chao() trong lớp A không khai báo virtual thì phương thức chao() sẽ không có tính đa hình, khi đó cả ba lần đều gọi chào của A
- Có thể gán địa chỉ của đt thuộc lớp con vào biến con trỏ, trỏ tới đt thuộc lớp cha nhưng không thể làm ngược lại (áp dụng nguyên tắc “con gán vào cha” đối với biến kiểu đối tượng hoặc biến kiểu con trỏ, trỏ tới đối tượng)
Câu 8: Trình bày vấn đề hình thoi trong đa kế thừa? Ví dụ minh họa?
Trả lời:
Vấn đề hình thoi:
Phát sinh khi một lớp con đa kế thừa từ hai hay nhiều lớp cơ sở Các lớp cơ sở lại kế thừa từ một lớp chung lớn hơn
Trong lớp con sẽ tồn tại hai thực thể của lớp chung do kế thừa từ các lớp cơ sở Khi lớp con thực hiện một phương thức nào đó của hai lớp cơ sở hay lớp chung
Trình biên dịch báo lỗi ambigous do không biết phải sử dụng phương thức của lớp cơ sở nào
Ví dụ:
Giải quyết vấn đề:
- Phương án 1: Định nghĩa lạo phương thức tinhChuVi cho lớp HinhThoi và
HinhChuNhat Khi gọi phương thức thì dùng toán tử :: như sau:
hv.HinhThoi::tinhChuVi() -> Chương trình có tính tổng quát không cao
- Phương án 2: Định nghĩa lại phương thức tinhChuVi cho lớp HinhVuong.
Trang 10-> Không truy xuất được thuộc tính từ lớp HinhBinhHanh.
=> Cách giải quyết tốt nhất: dùng kế thừa ảo
Trang 11Câu 9: Trình bày các tính chất của OOP? Ví dụ minh họa?
Trả lời:
Tính đóng gói: Sự đóng gói là cơ chế ràng buộc dữ liệu và thao tác trên dữ
liệu đó thành một thể thống nhất, tránh được các tác động bất ngờ từ bên ngoài Tính chất không cho phép người dùng hay đối tượng khác thay đổi dữ liệu thành viên của đối tượng nội tại Chỉ có các hàm thành viên của đối tượng đó mới có quyền thay đổi trạng thái nội tại của nó mà thôi
VD:
class Box
{
public:
double tinhTheTich(void)
{
return chieudai * chieurong * chieucao;
}
private:
double chieudai; // Chieu dai cua mot box
double chieurong; // Chieu rong cua mot box
double chieucao; // Chieu cao cua mot box
};
Các biến chieudai, chieurong, và chieucao là private Nghĩa là chúng chỉ có thể
được truy cập bởi các thành viên khác của lớp Box, và không thể bởi bất kỳ phần khác trong chương trình của bạn
Tính kế thừa: Tính kế thừa là khả năng cho phép ta xây dựng một lớp mới dựa trên các định nghĩa của một lớp đã có Lớp đã có gọi là lớp Cha, lớp mới phát sinh gọi là lớp Con Lớp Con được thừa hưởng các thuộc tính của lớp Cha, có thể bổ sung các thành phần hoặc định nghĩa là các thuộc tính của lớp cha
VD:
#include <bits/stdc++.h>
using namespace std;
//Lớp Cha
class Parent {
public:
int id_p;
};
// Lớp con kế/ thừa từ lớp cha
class Child : public Parent {
public:
int id_c;
};
Trang 12int main() {
Child obj1;
obj1.id_c = 7;
obj1.id_p = 91;
cout << "Child id is " << obj1.id_c << endl;
cout << "Parent id is " << obj1.id_p << endl;
return 0;
}
Kết quả:
Child id is 7
Parent id is 91
Trong chương trình trên, class Child là lớp con, nó sẽ được kế thừa các thành viên dữ liệu dạng public từ class Parent
• Tính đa hình: Cho phép các lớp được định nghĩa các phương thức trùng nhau: cùng tên, cùng số lượng và kiểu tham số, cùng kiểu trả về Việc định nghĩa phương thức trùng nhau của các lớp kế thừa nhau còn được gọi là sự nạp chồng phương thức
Khi gọi các phương thức trùng tên, dựa vào đối tượng đang gọi mà chương trình sẽ thực hiện phương thức của lớp tương ứng, và do đó, sẽ cho các kết quả khác nhau
VD:
#include <bits/stdc++.h>
using namespace std;
class OOP
{
public:
// Hàm có một tham số/
void func(int x)
{
cout << "value of x is " << x << endl;
}
// Hàm cùng tến có một tham số/ nhưng khác kiế* u
void func(double x)
{
cout << "value of x is " << x << endl;
}
// Hàm cùng tến nhưng có 2 tham số/
void func(int x, int y)
{
cout << "value of x and y is " << x << ", " << y << endl; }
};
Trang 13int main()
{
OOP obj;
obj.func(7);
obj.func(9.132);
obj.func(85, 64);
return 0;
}
Kết quả:
value of x is 7
value of x is 9.132
value of x and y is 85, 64
Trong ví dụ trên, ta chỉ dùng một hàm duy nhất có tên là func nhưng có thể dùng được cho 3 tình huống khác nhau Đây là một thể hiện của tính đa hình
Câu 10: Trình bày các thành phần của một lớp? Ví dụ minh họa?
Trả lời:
Một lớp gồm 2 thành phần:
+ Trường: (hay còn gọi là thuộc tính, biến thành viên) : Là các thuộc tính thể
hiện đặc điểm tính chất cho đối tượng
+ Phương thức: (hay còn được gọi là hành vi, hàm thành viên): Thể hiện các
hành động của đối tượng
Ví dụ:
Chúng ta mô hình hóa một vector hình học trong không gian 3d thành một lớp đối tượng trong c++
=> Trường: tọa độ x, y, z là các kiểu số thực
=> Phương thức: Các phép tính cho vector như là phép cộng, phép trừ, phép tích vô hướng…
Như vậy khi bắt đầu làm một bài toán lập trình hướng đối tượng,
chúng ta phải có bước phân tích dữ liệu để xác định được hai thành phần cho lớp đối tượng