Tải bản đầy đủ (.docx) (26 trang)

Hệ thống câu hỏi ôn tập OOP 2019

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 (262.97 KB, 26 trang )

Hệ thống câu hỏi ôn tập OOP 2019-2020
Câu 1: so sánh lập trình cấu trúc và hướng đối tượng
1. So sánh lập trình cấu trúc và lập trình hướng đối tượng
Lập trình cấu trúc
- Cấu trúc được thiết kế theo cách từ trên
xuống(top-down)
- Lấy thuật toán để xây dựng cấu trúc bài
- Cấu trúc được chia thành các thủ tục và
hàm
- Các chương trình con:
+ Độc lập với nhau và có DL riêng
+ Trao đổi qua tham số và biến toàn cục
- Làm việc thông qua gọi hàm và thủ tục

Lập trình hướng đối tượng
- Cấu trúc được thiết kế theo cách từ dưới
lên(bottom-up)
- Lấy đối tượng làm nền tảng xd thuật
toán.
- Cấu trúc được chia thành các lớp đối
tượng
- Dữ liệu được đóng gói, che giấu và bảo
vệ
- Đối tượng làm việc với nhau qua khai
báo

Câu 2: Trong C++ các hàm cùng tên được phân biệt với nhau bởi cái gì?
- Các hàm tải bội là các hàm có cùng một tên và có tập đối khác nhau (về số lượng các đối
hoặc kiểu). Khi gặp lời gọi các hàm tải bội thì trình biên dịch sẽ căn cứ vào số lượng và
kiểu các tham số để gọi hàm có đúng tên và đúng các tham số tương ứng.
Ví dụ: Chương trình tìm max của một dãy số nguyên và max của một dẫy số thực. Trong


chương trình có 6 hàm: hai hàm dùng để nhập dãy số nguyên và dãy số thực có tên chung
là nhapds, bốn hàm: tính max 2 số nguyên, tính max 2 số thực, tính max của dẫy số
nguyên, tính max của dẫy số thực được đặt chung một tên là max.
- Chú ý: Nếu hai hàm trùng tên và trùng đối thì trình biên dịch không thể phân biệt được.
Ngay cả khi hai hàm này có cùng kiểu khác nhau thì trình biên dịch vẫn báo lỗi. Ví dụ
sau xây dựng hai hàm cùng có tên là f và cùng một đối nguyên a, nhưng kiểu hàm khác
nhau. Hàm thứ nhất có kiểu nguyên( trả về a*a), hàm thứ hai có kiểu void. Chương trình
sau sẽ bị thông báo lỗi khi biên dịch.
Ví dụ:
#include <iostream.h>
#include <conio.h>
int f(int a);
void f(int a);
int f(int a)
{
1


return a*a;
}
void f(int a)
{
cout<<"\n"<}
void main()
{
int b = f(5);
f(b);
getch();
}

Câu 3: Ưu điểm của hàm nguyên mẫu (function prototypes) là gì?
- Hàm nguyên mẫu (Function Prototype) là một trog nhữg tính năng quan trọng của C++.
- Hàm nguyên mẫu cung cấp cho trình biên dịch (compiler) tên của hàm, kiểu dữ liệu mà
hàm trả về, số lượng các đối số mà hàm cần cung cấp, kiểu dữ liệu và thứ tự của các đối
số đó. Nhờ đó, hàm nguyên mẫu giúp cho trình biên dịch xác nhận các lời gọi hàm mà
chưa cần định nghĩa hàm đó. Hay nói cách khác. bạn có thể xem chúng giống như là một
lời hứa của bản thân đối với trình biên dịch rằng: “Tôi hứa sẽ định nghĩa hàm này cho
bạn. Vì thế, cứ yên tâm mà thực hiện những thao tác tiếp theo”.
- Cách sử dụng hàm nguyên mẫu rất đơn giản. Bạn chỉ việc khai báo theo mẫu sau:
data_type function_name(type_1 argument_1, type_2 argument_2, … , type_n argument_n);

- Ví dụ: int add(int a, int b);
Câu 4: Một lớp (class) là gì? Nó thực hiện việc che dấu dữ liệu như thế nào?
Lớp (Class)
- Một lớp là một bản thiết kế hoặc bản mẫu dùng để định nghĩa các biến (dữ liệu) vàphương
thức (lệnh) cho tất cả các đối tượng cùng loại Lớp sử dụng như là một kiểu do ngườidùng
định nghĩa. Do đó một lớp định nghĩa kiểu dữ liệu giống như kiểu dữ liệu sẵn có củamột
ngôn ngữ lập trình. Một đối tượng là một sự thể hiện cụ thể của một lớp.
- Việc truy xuất các biến và các phương thức được khai báo trong lớp phụ thuộc vào
việckhai báo chúng là riêng (private) hay chung (public).Một biến được khai báo là public
sẽđược nhìn thấy ở mọi nơi.Còn biến khai báo là private sẽ không xuất hiện bên ngoài của
lớp.
2


- Tóm lại, lớp (class) là nhóm các đối tượng có cùng thuộc tính, cùng hành vi và cùngmối
liên hệ. Mối đối tượng được coi là một sự thể hiện (instant) của một lớp.
- Ví dụ: một lớp phân số bao gồm tử số, mẫu số được khai báo private, các hàm nhập , in, tối
giản, cộng hai phân số, tích hai phân số khai báo public……….
Thực hiện việc che giấu dữ liệu: Quyền truy xuất: là khả năng truy xuất thành phần dữ liệu

của các hàm thành phần:
- private: chỉ quyền truy xuất trong phạm vi lớp đó (bởi các hàm thành phần trong lớp)
- public: được truy xuất ở mọi nơi nếu đối tượng đó tồn tại
- protected: chỉ được truy xuất trong phạm vi lớp đó và các lớp con kế thừa từ nó.
 Phạm vi tác động của 1 từ khóa quyền truy xuất kà từ lúc nó xuất hiện cho đến hết khai
báo lớp hoặc gặp từ khóa xác định quyền truy xuất khác.



Nếu không xác định quyền truy xuất thì ngầm định là private. Ở kiểu dữ liệu cấu
trúc, các thành phần dữ liệu đều có quyền truy xuất là public, nghĩa là các dữ liệu này có
quyền truy nhập ở mọi nơi. Đó là yếu điểm của kiểu dữ liệu cấu trúc, lớp đã khắc phục
nhược điểm này bằng cách cho quyền truy xuất mặc định các thành phần dữ liệu là
private, chỉ có các hàm trong lớp mới có quyền truy xuất các thành phần dữ liệu này.

Câu 5: So sánh một struct ( cấu trúc) và một class ( lớp) trong C++
Giống: đều là kiểu DL người dùng định nghĩa
Khác:
Lớp
-Lớp là tập hợp các đối tượng có cùng thuộc
tính và hành vi, là bản thiết kế hoặc bản mẫu
mô tả một CTDL gồm các thành phần DL và
các phương thức
-DL trong lớp được bao gói, che giấu

Cấu trúc
-Thành phần của cấu trúc chỉ có DL.
-DL trong cấu trúc có bao gói nhưng ko che
giấu


Câu 6: Đối tượng là gì? Lớp là gì? Nó được tạo ra như thế nào?
 Khái niệm đối tượng( Objects):
- Đối tượng mô tả sự vật tồn tại hoặc khái niệm trong đời sống thực tế. Ví dụ, một đối tượng
có thể mô tả một khái niệm vật lý như nhân viên, công ty, hoặc ô tô, nó cũng mô tả một cái
gì đó trừu tượng như hình tròn, điểm, …

3


- Về phương diện lập trình đối tượng được định nghĩa là một sự thể hiện của một lớp. Nó
còn được định nghĩa là phiên bản trong khi thi hành của lớp. Đốitượng chính là các thực
thể cơ bản trong hệ thống hướng đối tượng. Mỗi đối tượng được baohàm bởi tên và trạng
thái (dữ liệu của nó). Các biến trong đối tượng chỉ rõ mọi thông tin vềtrạng thái của đối
tượng (state) còn các phương thức thì xác định nó có thể sử dụng như thếnào (behavior).
- Ví dụ, một cái xe đạp có một trạng thái (số bánh xe và bánh răng), và các thaotác (phanh,
tăng tốc, giảm tốc, thay đổi bánh răng).

Câu 7 : Một hàm thành phần của lớp được định nghĩa như thế nào?
Một hàm thành viên của một lớp là một hàm mà có định nghĩa hoặc prototype của nó bên trong
định nghĩa lớp giống như bất kỳ biến nào khác. Nó hoạt động trên bất kỳ đối tượng nào của lớp
mà nó là một thành viên, và có sự truy cập tới tất cả thành viên của một lớp cho đối tượng đó.
Chúng ta truy cập các thành viên của lớp bởi sử dụng một hàm thành viên thay vì trực tiếp truy
cập chúng:
class Box
{
public:
double chieudai; // chieu dai cua hop
double chieurong; // chieu rong cua hop
double chieucao; // chieu cao cua hop
double thetich(void);// tra ve the tich cua hop

};
Các hàm thành viên có thể được định nghĩa bên trong định nghĩa lớp hoặc sử dụng toán tử
phân giải phạm vi ::. Định nghĩa một hàm thành viên bên trong định nghĩa lớp sẽ khai báo
hàm inline, ngay cả khi bạn không sử dụng inline specifier. Vì thế, bạn có thể định nghĩa
hàm Volume() như sau:
class Box
{
public:
4


double chieudai; // chieu dai cua hop
double chieurong; // chieu rong cua hop
double chieucao; // chieu cao cua hop
double thetich(void)
{
return chieudai * chieurong * chieucao;
}
};
Nếu bạn thích, bạn có thể định nghĩa giống hàm đó ở bên ngoài lớp bởi sử dụng toán tử phân
giải phạm vi :: như sau:
double Box::thetich(void)
{
return chieudai * chieurong * chieucao;
}
Tại đây, chỉ có một điểm quan trọng là bạn sẽ phải sử dụng tên lớp ngay trước toán tử ::. Một
hàm thành viên sẽ được gọi bởi sử dụng một toán tử dot (.) trên một đối tượng, nơi mà nó sẽ
thao tác dữ liệu chỉ liên quan tới đối tượng đó, như sau:
Box hopQua;


// tao mot doi tuong

hopQua.thetich(); // goi ham thanh vien cho doi tuong nay
Câu 8: Một thành phần của lớp được khai báo là tĩnh (static) khi nào? Hàm thành phần
tĩnh?
a. Dữ liệu tĩnh
- Khai báo:
static <kiểu dữ liệu> <tên thành phần>;
- Ví dụ:
5


class PS{ int ts, ms;
static int count;
public:
PS(int m=0, int n=1){ ts=t; ms=m; count++;}
};
- Truy xuất:
 Theo đối tượng (cách thông thường)
Ví dụ:
PS a;
a.count=0;
 Theo lớp
Ví dụ:
PS::count=0;
- Chú ý:
 Tồn tại ngay khi chưa có đối tượng nào
 Phải được khởi tạo trước khi đối tượng phát sinh
 Phải khởi tạo ngoài mọi hàm theo cú pháp:
<kiểu dl> <tên lớp>::<tên thành phần dl> = <giá trị>;

Ví dụ: int PS::count=0;
b. Phương thức tĩnh
- Khái niệm:
 là hàm thành phần của lớp nhưng không gắn với đối tượng cụ thể nào
 Dùng để thao tác chung cho lớp
 Trong thân hàm không có đối tượng ẩn
static <kiểu dl trả về> <tên hàm>(tham số);
Ví dụ: xây dựng lớp SV gồm pt nhập, in 1 sinh viên. Nhập, in danh sách sinh viên.
6


Câu 9. Hàm bạn là gì?Lớp bạn là gì? Ưu điểm và nhược điểm khi sử dụng hàm bạn.
Hàm bạn
Khái niệm:
Hàm bạn của 1 lớp là
 Hàm được khai báo bên trong lớp và đươc định nghĩa bên ngoài phạm vi lớp đó
 Có khả năng truy cập đến các thành viên private và protected của một lớp
 Không là hàm thành viên của lớp
Cú pháp:
friend< kiểu_trả_về><tên_hàm>([danh sách tham số]);
Tính chất:
 Trong thân hàm bạn của một lớp có thể truy nhập tới các thuộc tính của các đối tượng
thuộc lớp này( không bị ảnh hưởng của từ khóa truy xuất). Đây là sự khác nhau duy nhất
giữa hàm bạn và hàm thông thường.
 Hàm bạn không phải là phương thức của một lớp, lời gọi của hàm bạn giống như lời gọi
của hàm thông thường.
 Không hạn chế số lượng hàm bạn
Ưu điểm:
 Kiểm soát các truy nhập ở cấp độ lớp. Nghĩa là không thể áp đặt hàm bạn cho một lớp,
nếu như chưa khai báo hàm bạn trong lớp.

 Giải quyết được vấn đề cần truy cập dữ liệu của lớp như trên.
Ví dụ: viết chương trình nhập phân sốcó một hàm bạn tính tích hai phân số, in kết quả.
#include<stdio.h>
#include<conio.h>
#include<iostream.h>
class ps
{
int ts, ms;
public:
void nhap()
{
cout<<"\n nhap tu so: ";
cin>>ts;
cout<<"\n nhap mau so: ";
cin>>ms;
7


}
void in()
{
cout<<" \nket qua la: "<}
friend ps nhan( ps, ps);
};
ps nhan(ps a, ps b)
{
ps kq;
kq.ts=a.ts*b.ts;
kq.ms=a.ms*b.ms;

return kq;
}
main()
{
ps a,b;
a.nhap();
b.nhap();
nhan(a,b).in();
getch();
}
Lớp bạn:
Khái niệm:
Lớp A là lớp bạn của lớp B nếu trong B có chứa khai báo: friend class A;
Tính chất: A là lớp bạn của B thì mọi thành phàn của A là hàm bạn của B
Ví dụ:
#include<iostream.h>
#include<string.h>
Class nv
{
Int manhanvien;
Char tennv;
Int luong;
Public:
Friend class boss; //lop nv khai bao lop boss la ban
Void nhap();
8


Void in();
};

Class boss
Int maboss;
Char tenboss;
Public:
Void tinhluong( nv &e, int s)
{
e.luong=e.luong+s;
}
};
Câu 10. Hàm khởi tạo là gì? Có bắt buộc phải sử dụng hàm khởi tạo trong một lớp?
- Hàm khởi tạo là một hàm thành phần đặc biệt của lớp cho phép khởi tạo đối tượng; nó
được gọi thực hiện một cách tự động khi đối tượng phát sinh.
- Hàm tạo là bắt buộc khi định nghĩa class. Tuy nhiên chương trình dịch của C# có khả năng
tự sinh hàm tạo cho class nếu nó không nhìn thấy định nghĩa hàm tạo nào trong class. Loại
hàm tạo này có tên gọi là hàm tạo mặc định (default constructor). Hàm tạo mặc định
không có tham số đầu vào.
+ Nếu trong khai báo class chúng ta tự viết một hàm tạo không có tham số đầu vào, hàm
tạo này không được gọi là hàm tạo mặc định nữa mà được gọi là hàm tạo không tham
số (parameter-less/zero-parameter constructor), vì nó không phải do chương trình dịch của
C# sinh ra.
+ Trong ví dụ trên, public Book() {...} là một hàm tạo không tham số nhưng nó không
phải là hàm tạo mặc định.
+ Một khi đã định nghĩa hàm tạo riêng trong class, C# compiler sẽ không tự sinh ra hàm
tạo mặc định nữa. Nghĩa là nếu bạn muốn gọi hàm tạo không tham số, bạn phải tự viết
thêm hàm tạo đó. Nếu không, quá trình dịch sẽ báo lỗi.

Câu 11. Hàm khởi tạo, hàm hủy được gọi như thế nào?
I. Hàm khởi tạo và hàm hủy lớp cơ sở
1. Hàm khởi tạo
9



- Hàm khởi tạo là hàm thành phần đặc biệt của lớp cho phép khởi tạo đối tượng, nó được gọi
thực hiện một cách tự động khi đối tượng phát sinh.
Khai báo: <tên_lớp>([ds tham số]);
Định nghĩa:
<tên_lớp>::tên_lớp([ds tham số])
{
//thân hàm
}
VD: class SV
{SV
Cout<<”Đay la ham khoi tao lop sv: “;
};
-Một số hàm khởi tạo
+ hàm khởi tạo mặc định: là hàm khởi tạo được gọi khi đối tượng được khai báo mà ko có đối
số
+Hàm khởi tạo sao chép là hàm khởi tạo đặc biệt khi ta gọi đối tượng mới là bản sao của đối
tượng đã có sẵn
<tên_lớp>([const]<tên_lớp>&<tên_tham_số>);
2. Hàm hủy của lớp cơ sở
-Hàm hủy là một hàm thành phần của lớp với chức năng hủy bỏ, giải phóng các đối tượng khi
nó hết phạm vi tồn tại.
-Khai báo: ~<tên_lớp>();
VD: ~SV();
II. Hàm hủy và hàm khởi tạo của nhiều lớp
1. Hàm khởi tạo
-Hàm khởi tạo của lớp cha ko được kế thừa
10



-Thứ tự gọi hàm: Hàm khởi tạo lớp cha->hàm khởi tạo lớp con
-Khai báo:
<hàm khởi tạo dẫn xuất>([tham số]:<hàm khởi tạo cơ sở>([tham số])
{
//thân hàm khởi tạo
}
VD:
Class A
{
Public:
A()
{cout<<”ham khoi tao cua A\n”;}
};
Class B:public A
{
Public:
B()
{cout<<”ham khoi tao cua B\n”;}
};
Void
{ B b;
}
2. Hàm hủy
-hàm hủy của lớp cơ sở ko được kế thừa
11


-hàm hủy của lớp dấn xuất thi hành trước hàm hủy của lớp cơ sở.
VD: ~B();

~A();

Câu 12. Liệt kê các đặc điểm quan trọng của hàm khởi tạo.
- Hàm khởi tạo có với mọi lớp
- Tên hàm giống như tên lớp
- Hàm tạo không có kiểu nên không cần khai báo
- Hàm tạo không có giá trị trả về
- Nếu lập trình viên không xây dựng hàm khởi tạo thì chương trình sẽ tự động sinh ra hàm khởi
tạo mặc định
- Không được phép gọi các hàm khởi tạo một cách tường minh bởi chúng được gọi tự động khi
khai báo các thể hiện của lớp.
Câu 13. Có thể có nhiều hơn một hàm khởi tạo trong lớp không? Nếu có, hãy đưa ra những
gì là cần thiết khi có nhiều hàm khởi tạo.
- Trong một lớp, bạn hoàn toàn có thể có nhiều constructor, mỗi constructor như vậy
phải khác tham số truyền vào (chứ không phải khác tên nhé, như trên kia có nói rằng
constructor phải cùng tên với tên lớp, như vậy các constructor đều phải có tên giống
nhau )
- Với một lớp có nhiều constructor, bạn hoàn toàn có thể từ constructor này gọi đến
constructor khác, việc gọi đến này không tạo thêm một thể hiện mới của lớp, mà mục
đích chính của việc này là để tận dụng lại các dòng code khởi tạo của các constructor
- Dù cho lớp đó có bao nhiêu constructor đi nữa, thì khi khai báo đối tượng, bạn phải chỉ
định một và chỉ một constructor
Câu 14. Hàm khởi tạo là gì? Những đặc điểm quan trọng của hàm khởi tạo.
- Hàm khởi tạo là hàm thành phần đặc biệt của lớp cho phép khởi tạo đối tượng, nó được gọi
thực hiện một cách tự động khi đối tượng phát sinh.
Khai báo: <tên_lớp>([ds tham số]);
12


Định nghĩa:

<tên_lớp>::tên_lớp([ds tham số])
{
//thân hàm
}
VD: class SV
{SV
Cout<<”Đay la ham khoi tao lop sv: “;
};
-Một số hàm khởi tạo
+ hàm khởi tạo mặc định: là hàm khởi tạo được gọi khi đối tượng được khai báo mà ko có đối
số
+Hàm khởi tạo sao chép là hàm khởi tạo đặc biệt khi ta gọi đối tượng mới là bản sao của đối
tượng đã có sẵn
<tên_lớp>([const]<tên_lớp>&<tên_tham_số>);
- Hàm khởi tạo có với mọi lớp
- Tên hàm giống như tên lớp
- Hàm tạo không có kiểu nên không cần khai báo
- Hàm tạo không có giá trị trả về
- Nếu lập trình viên không xây dựng hàm khởi tạo thì chương trình sẽ tự động sinh ra
hàm khởi tạo mặc định
- Không được phép gọi các hàm khởi tạo một cách tường minh bởi chúng được gọi tự
động khi khai báo các thể hiện của lớp.
Một số hàm khởi tạo:
- Hàm khởi tạo mặc định (default constructor): là hàm khởi tạo được gọi khi đối tượng
13


được khai báo mà không có đối số
- Hàm khởi tạo sao chép (copy destructor)là hàm khởi tạo đặc biệt khi ta gọi đối tượng
mới là bản sao của đối tượng đã có sẵn

Khai báo:
<tên lớp>([const] <tên lớp> & <tên tham số>);
ví dụ:
class PS
{
int tso, mso;
public:
PS(){int ts=0;int ms=1;};
PS(const PS &);
void nhap();
void in();
void toigian();
}
PS::PS(const PS & a)
{
tso=a.tso;
mso=a.mso;
}
void main()
{
PS p;
14


PS q(p); //Tạo q theo p
}
Câu 15. Nạp chồng toán tử là gì? Tại sao lại cần phải nạp chồng toán tử.?
- Cú pháp:
<kiểu trả về>operator<tên toán tử>([ds tham số])
- Định nghĩa ngoài lớp:

<kiểu trả về><tên_lớp>::operator<tên toán tử>([ds tham số])
{
//thân hàm
}


-

Ví dụ:
Nạp chồng toán tử +, * của lớp phân số
Nạp chồng toán tử + vector
Danh sách các toán tử có thể nạp chồng:

+ - * / = < > += -= *= /= << >>
<<= >>= == != <= >= ++ -- % & ^ ! |
~ &= ^= |= && || %= [] () , ->* -> new delete new[] delete[]






Chú ý:
Chỉ có thể định nghia lại các toán tử ở trên
Không làm thay đổi độ ưu tiên của các toán tử
Với toán tử 2 ngôi: toán tử bên trái là ẩn toán tử bên phải là đối số
Do đó: số tham số bằng số toán hạng – 1
Cách gọi hàm toán tử:
Dùng như cú pháp thông thường của phép toán


Ví dụ: PS a,b,c; c=a+b;
 Dùng như hàm thành phần của đối tượng
Ví dụ:
15


PS a,b,c;
c=a.operator+(b);
Câu 17. Cần bao nhiêu tham số trong định nghĩa của nạp chồng toán tử một ngôi
 nạp chồng toán tử 1 ngôi ( chỉ có thể truyền vào một tham số )
Câu 18. Cần bao nhiêu tham số trong định nghĩa của nạp chồng toán tử hai ngôi
Với cách nạp chồng toán tử 2 ngôi này, thì hàm nạp chồng được coi là một hàm bạn của lớp:
 Có từ khoá friend ở đầu
 Tên hàm là operator @– Trong đó @ vẫn là toán tử cần nạp chồng
 2 tham số được truyền vào là 2 giá trị thực hiện phép toán

Câu 19. Kế thừa có nghĩa là gì trong C++
- 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
Ví dụ 1:
Xây dựng lớp PS1 {ts, ms, nhập, in, tối giản}
Lớp PS2 {ts, ms, nhập, in, tối giản, cộng, trừ, nhân chia phân số}



Kế thừa tạo ra mô hình phân cấp: PS1<- PS2 , Người ( A, B)
Các loại kế thừa:
Kế thừa đơn: chỉ có một lớp cơ sở
Đa kế thừa: có nhiều hơn một lớp cơ sở


Câu 21. Nhiều dạng (forms) của kế thừa là gì? Cho ví dụ minh họa.
- Cú pháp
class <tên lớp con>:[kiểu dẫn xuất]<tên lớp cha1>,[kiểu dẫn xuất]<tên lớp cha 2>…..
{// Các thành phần của lớp con};
16


- Hai kiểu kế thừa chính: private và public ngoài ra còn kiểu kế thừa là protected. Mặc định
các lớp dẫn xuất sẽ kế thừa các lớp cơ sở theo kiểu private, muốn kế thừa theo kiểu public
ta phải khai báo tường minh như ở trên để trình biên dịch biết. Kiểu kế thừa chi phối
quyền truy xuất tới các phần tử của các lớp cơ sở khác nhau. Khi sử dụng kế thừa public,
mọi thành phần được khai báo ở lớp cơ sở là private sẽ trở thành private ở lớp con. Tương
tự, các thành phần khai báo là public ở lớp cha thì ở lớp con cũng sẽ là public.
- Khi sử dụng kế thừa kiểu private thì lại khác

Câu 22. Trình bày cú pháp khi báo đơn kế thừa trong C++
- Đơn kế thừa: nghĩa là một lớp chỉ được kế thừa từ đúng một lớp khác. Hay nói cách khác,
lớp con chỉ có duy nhất một lớp cha.
- Cú pháp khai báo đơn kế thừa
class <tên lớp con>:[kiểu dẫn xuất]<tên lớp cha1>
{
// Các thành phần của lớp con
};
VD:
#include <iostream>
using namespace std;
// Lớp cha
class Vehicle
{

public:
Vehicle()
{
cout << "This is a Vehicle" << endl;
}
};
17


// Lớp con kế thừa từ lớp cha
class Car : public Vehicle
{
};
// ct chính
int main()
{
Car obj;
return 0;
}
Câu 23. Trình bày cú pháp khi báo đa kế thừa trong C++
- Đa kế thừa là một tính năng của ngôn ngữ C++. Trong đó một lớp có thể kế thừa từ nhiều
hơn một lớp khác. Nghĩa là một lớp con được kế thừa từ nhiều hơn một lớp cơ sở.
- Khai báo
class <tên lớp con>:[kiểu dẫn xuất]<tên lớp cha1>,[kiểu dẫn xuất]<tên lớp cha 2>…..
{// Các thành phần của lớp con};
- VD:
#include <iostream>
using namespace std;
// Lớp cơ sở thứ nhất
class Vehicle

{
public:
Vehicle()
{
cout << "This is a Vehicle" << endl;
}
};
// Lớp cơ sở thứ hai
class FourWheeler
{
public:
FourWheeler()
{
cout << "This is a 4 wheeler Vehicle" << endl;
}
};
18


// Lớp con kế thừa từ 2 lớp cha
class Car : public Vehicle, public FourWheeler
{
};
// main function
int main()
{
Car obj;
return 0;
}
Câu 24. Lớp cơ sở ảo là gì? Khi nào thì tạo lớp cơ sở ảo?

- Xét trường hợp 1:
+ giả sử trong lớp A có thành phần x
+ trong lớp B cũng có thành phần x
+ xây dựng lớp C kế thừa từ lớp A và B
 Theo nguyên lý kế thừa trong lớp C sẽ có 2 thành phần x
Vấn đề xảy ra : khi truy cập thành phần x trong C thì chương trình dich không biết x
đó là của lớp A hay của lớp B
 Đây là sự nhập nhằng trong đa kế thừa
Giải quyết: ta xác định phạm vi tường minh
VD: C c;
c.A::x hoặc c.B::x
Xét trường hợp 2:
+ gọi lớp A là cơ sở của lớp B và C
+ gọi D là lớp dẫn xuất của lớp B và C

Giải quyết:
+ Khai báo tường minh
<tên đối tượng>.sở>::<tên thành phần>;
+ Coi A là lớp cơ sở ảo của cả B
và C. Khi đó D chỉ có một sự thể
hiện của A
Khai báo:
19


class<tên lớp dẫn xuất>: virtual <kiểu dẫn xuất><lớp cơ sở>;
Khi đó ta khai báo:
class B: virtual public A {…}
class C: virtual public B {…}

ví dụ: giả sử có lớp động vật như sau:
class Animal
{
virtual void eat();
};
// lớp động vật có vú kế thừa từ lớp động vật
class Mammal
{
public:
virtual Color getHairColor();
};
// lớp động vật có cánh kế thừa lớp động vật
class WingeAnimal
{
public:
virtual void Flap();
};
// loài dơi có vú biết bay nên kế thừa cả 2 lớp động vật có vú và có cánh
class Bat: public Mammal, public: WimgedAnimal{};
Vấn đề đặt ra là loài dơi ăn như thế nào tức là sử dụng phương thức eat() nào? Nếu như khai
báo ở trên thì việc gọi Bat.eat() là nhập nhằng không rõ ràng. Khi đó có thể gọi là
Bat.WingedAnimal::eat(); hoặc Bat.Mammal::eat();
20


Sử dụng kế thừa ảo sẽ giải quyết được vấn đề này. Chúng ta sẽ khai báo như sau:
…..
class Mammal: public virtual Animal
{
public:

virtual Color GetHairColor();

};
class WingeAnimal: public virtual Animal
{
public:
virtual void Flap();
};
//loài dơi vẫn là động vật có vú
class Bat: public Mammal, public: WingeAnimal
{
};

Câu 25. Lớp trừu tượng là gì?
- Lớp trừu tượng là một trong những khái niệm quan trọng trên nền tảng .NET. Thường,
bạn muốn tạo ra các lớp mà chỉ làm lớp gốc (base class – lớp đầu tiên trong cây thừa kế
hay còn gọi là lớp tổ tiên), và dĩ nhiên, bạn sẽ không muốn người khác tạo ra đối tượng
cho các lớp này. Chúng ta có thể sử dụng khái niệm lớp trừu tượng để cài đặt chức năng
này trong C# sử dụng từ khóa ‘abstract‘.

21


- Một lớp trừu tượng có nghĩa là không khởi tạo được đối tượng của lớp này, nhưng cho
phép thừa kế để tạo ra lớp con.
Khai báo lớp trừu tượng trong C#:
abstract class tên_lớp_trừu_tượng
{
}


Câu 26. Đa hình có nghĩa là gì trong C++
- Đa hình (polymorphism) nghĩa là có nhiều hình thái khác nhau. Tiêu biểu là, đa hình
xuất hiện khi có một cấu trúc cấp bậc của các lớp và chúng là liên quan với nhau bởi tính
kế thừa.
- Đa hình trong C++ nghĩa là một lời gọi tới một hàm thành viên sẽ làm cho một hàm khác
để được thực thi phụ thuộc vào kiểu của đối tượng mà triệu hồi hàm đó.
Câu 27. Đa hình được thực hiện như thế nào trong biên dịch và lúc chạy chương trình?
- Khi đối tượng nhận một thông báo thực hiện một phương thức, hệ thống sẽ:
 Kiểm tra cú pháp của thông báo
 Gắn thông báo đó với 1 định nghĩa hàm cụ thể
- Việc kết gán có thể xảy ra ở hai thời điểm:
 Lúc biên dịch chương trình -> Kết gán sớm
 Lúc chạy chương trình -> Kết gán muộn
Câu 28. Hàm ảo là gì? Tại sao cần có hàm ảo?
- Định nghĩa:
 Hàm ảo là hàm thành phần của lớp
 Được khai báo trong lớp cơ sở và định nghĩa lại trong lớp dẫn xuất
- Cú pháp
virtual <kiểu trả về> <tên hàm>([tsố])
- Một số chú ý:
 Định nghĩa các phương thức áo như các phương thức thông thường
 Sử dụng con trỏ để truy cập tới hàm ảo
 Định nghĩa trong lớp cơ sở ngay cả khi nó không được sử dụng
22











-

-

Không có hàm khởi tạo ảo nhưng có thể có hàm huỷ ảo
Con trỏ của lớp cơ sở có thể chứa địa chỉ của đối tượng lớp dẫn xuất
Cơ chế kết gán muộn:
Khi một lớp có phương thức ảo hoặc lớp cơ sở có phương thức áo
Chương trình dịch sẽ phát sinh thêm một con trỏ ảo (virtual pointer)
Con trỏ này trỏ tới một bảng ảo (Vtable)
Bảng ảo có chứa địa chỉ của các phương thức ảo
Quá trình phát sinh một đối tượng lớp dẫn xuất:
B1: xác định các thành phần ( ko ảo) kể cả cả các thành phần của lóp cơ sở
Bước 2: Xây dựng con trỏ ảo và bảng áo
Khi kết gán muộn, căn cứ vào con trỏ ảo để xác định phương thức trong bảng ảo và
phương thức của lớp dẫn xuất
Cơ chế kết gán phương thức ảo chỉ có thể thực hiện qua phép gán con trỏ hoặc tham
chiếu

VD: Xây dựng lớp giáo viên và sinh viên kế thừa từ lớp người
NGUOI
{
- ht,namsinh
- nhap, in
- loai(){returrn 0};
}

SV:NGUOI
{
-lop,dtb
-nhap, in
-loai(){ return 1;}
}
GV:NGUOI
{
23


-hsl, dv
-nhap,in
-loai(){return 2;}
}
Câu 29. Khi nào thì nên tạo một hàm ảo thuần túy.
- Mục đích:
 Tránh lãng phí bộ nhớ
 Cung cấp một phương thức thống nhất làm giao diện chung.
- Khai báo:
virtual <kiểu trả về> <tên phương thức>([tsố])=0;
- Đặc điểm:
 Không bắt buộc định nghĩa trong lớp cơ sở
 Không thể khai báo đối tượng thuộc lớp có phương thức ảo thuần tuý
 Lớp có phương thức ảo thuần tuý chỉ làm lớp cơ sở cho lớp khác và gọi là lớp cơ sở trừu
tượng
 Lớp dẫn xuất kế thừa lớp cơ sở trừu tượng mà không định nghĩa lại phương thức ảo
thuần tuý => nó trở thành lớp cơ sở trừu tượng

24



MỤC LỤC
Câu 1: so sánh lập trình cấu trúc và hướng đối tượng..............................................................................1
Câu 2: Trong C++ các hàm cùng tên được phân biệt với nhau bởi cái gì?...............................................1
Câu 3: Ưu điểm của hàm nguyên mẫu (function prototypes) là gì?.........................................................2
Câu 4: Một lớp (class) là gì? Nó thực hiện việc che dấu dữ liệu như thế nào?.........................................2
Câu 5: So sánh một struct ( cấu trúc) và một class ( lớp) trong C++........................................................3
Câu 6: Đối tượng là gì? Lớp là gì? Nó được tạo ra như thế nào?.............................................................3
Câu 7 : Một hàm thành phần của lớp được định nghĩa như thế nào?.......................................................4
Câu 8: Một thành phần của lớp được khai báo là tĩnh (static) khi nào? Hàm thành phần tĩnh?................5
Câu 9. Hàm bạn là gì?Lớp bạn là gì? Ưu điểm và nhược điểm khi sử dụng hàm bạn..............................7
Câu 10. Hàm khởi tạo là gì? Có bắt buộc phải sử dụng hàm khởi tạo trong một lớp?.............................9
Câu 11. Hàm khởi tạo, hàm hủy được gọi như thế nào?...........................................................................9
Câu 12. Liệt kê các đặc điểm quan trọng của hàm khởi tạo...................................................................12
Câu 13. Có thể có nhiều hơn một hàm khởi tạo trong lớp không? Nếu có, hãy đưa ra những gì là cần
thiết khi có nhiều hàm khởi tạo..............................................................................................................12
Câu 14. Hàm khởi tạo là gì? Những đặc điểm quan trọng của hàm khởi tạo.........................................12
Câu 15. Nạp chồng toán tử là gì? Tại sao lại cần phải nạp chồng toán tử.?...........................................14
Câu 17. Cần bao nhiêu tham số trong định nghĩa của nạp chồng toán tử một ngôi................................15
Câu 18. Cần bao nhiêu tham số trong định nghĩa của nạp chồng toán tử hai ngôi.................................16
Câu 19. Kế thừa có nghĩa là gì trong C++..............................................................................................16
Câu 21. Nhiều dạng (forms) của kế thừa là gì? Cho ví dụ minh họa......................................................16
Câu 22. Trình bày cú pháp khi báo đơn kế thừa trong C++....................................................................17
Câu 23. Trình bày cú pháp khi báo đa kế thừa trong C++......................................................................18
Câu 24. Lớp cơ sở ảo là gì? Khi nào thì tạo lớp cơ sở ảo?.....................................................................19
Câu 25. Lớp trừu tượng là gì?................................................................................................................21
Câu 26. Đa hình có nghĩa là gì trong C++..............................................................................................22
Câu 27. Đa hình được thực hiện như thế nào trong biên dịch và lúc chạy chương trình?......................22
Câu 28. Hàm ảo là gì? Tại sao cần có hàm ảo?......................................................................................22


25


×