Lập trình C++ - Phạm vi truy xuất

Phạm vi truy xuất trong kế thừa

Khi cài đặt kế thừa trong lập trình hướng đối tượng người ta vẫn phải quan tâm đến tính đóng gói và che giấu thông tin. Điều này ảnh hưởng đến phạm vi truy xuất các thành phần trong class.

Phạm vi truy nhập 
Mối quan hệ giữa các thành phần của lớp cơ sở và lớp dẫn xuất được quy định bởi các từ khóa dẫn xuất.

Kiểu dẫn xuất Tính chất ở lớp cơ sở Tính chất ở lớp dẫn xuất
private private protected Không truy nhập được private
  public private
protected private protected public Không truy nhập được protected protected
public private protected public Không truy nhập được protected public

Ta xét phạm vi truy nhập theo hai loại: 

  • Phạm vi truy nhập từ các hàm bạn, lớp bạn của lớp dẫn xuất 
  • Phạm vi truy nhập từ các đối tượng có kiểu lớp dẫn xuất 

Truy nhập từ các hàm bạn và lớp bạn của lớp dẫn xuất 

Nhìn vào bảng tổng kết trên, phạm vi truy nhập của hàm bạn, lớp bạn của lớp dẫn xuất vào lớp cơ sở như sau: 

  • Với dẫn xuất private, hàm bạn có thể truy nhập được các thành phần protected và public của lớp cơ sở vì chúng trở thành các thành phần private của lớp dẫn xuất, có thể truy nhập được từ hàm bạn. 
  • Với dẫn xuất protected, hàm bạn cũng có thể truy nhập được các thành phần protected và public của lớp cơ sở vì chúng trở thành các thành phần protected của lớp dẫn xuất, có thể truy nhập được từ hàm bạn. 
  • Với dẫn xuất public, hàm bạn cũng có thể truy nhập được các thành phần protected và public của lớp cơ sở vì chúng trở thành các thành phần protected và public của lớp dẫn xuất, có thể truy nhập được từ hàm bạn. 
  • Đối với cả ba loại dẫn xuất, hàm bạn đều không truy nhập được các thành phần private của lớp cơ sở, vì các thành phần này cũng không truy nhập được từ lớp dẫn xuất. 
Kiểu dẫn xuất Tính chất ở lớp cơ sở Tính chất ở lớp dẫn xuất Truy nhập từ hàm bạn của lớp dẫn xuất Truy nhập từ đối tượng của lớp dẫn xuất
private private protected public --- private private --- ok ok --- --- ---
protected private protected public --- protected protected --- ok ok --- --- ---
public private protected public --- protected public --- ok ok --- --- ok

Sử dụng các thành phần của lớp cơ sở từ lớp dẫn xuất 

Từ bảng tổng kết phạm vi truy nhập, ta thấy rằng chỉ có dẫn xuất theo kiểu public thì đối tượng của lớp dẫn xuất mới có thể truy nhập đến các thành phần (thuộc loại public) của lớp cơ sở. Khi đó, việc gọi đến các thành phần của lớp cơ sở cũng tương tự như gọi các thành phần lớp thông thường: 

  •  Đối với biến đối tượng thông thường: 
    <Tên đối tượng>.<Tên thành phần>([Các đối số]); 
  •  Đối với con trỏ đối tượng: 
    <Tên đối tượng>-><Tên thành phần>([Các đối số]); 

Lưu ý: 

  • Cách gọi hàm thành phần này được áp dụng khi trong lớp dẫn xuất, ta không định nghĩa lại các hàm thành phần của lớp cơ sở. 

Ví dụ: việc sử dụng các thành phần lớp cơ sở từ đối tượng lớp dẫn xuất: lớp Bus kế thừa từ lớp Car. Lớp Bus có định nghĩa bổ sung một số phương thức và thuộc tính mới. 
Khi đó, đối tượng của lớp Bus có thể gọi các hàm public của lớp Bus cũng như của lớp Car. 

#include<iostream>
#include<string>

using namespace std;
/* Định nghĩa lớp */
class Car {
private:
	int  speed;               // Tốc độ  
	string  mark;           // Nhãn hiệu
	float price;               // Giá xe 
public:
	Car(int speed, string mark, float price);
	void	setSpeed(int);     // Gán tốc độ cho xe
	int		getSpeed();           // Lấy tốc độ xe    
	void	setMark(string);      // Gán nhãn cho xe     
	string 	getMark();           // Lấy nhãn xe      
	void	setPrice(float);      // Gán giá cho xe     
	float	getPrice();           // Lấy giá xe	
	void	show();               // Hiển thị thông tin về xe
};

/* Khai báo phương thức bên ngoài lớp */
void Car::setSpeed(int speedIn) { // Gán tốc độ cho xe   
	speed = speedIn;
}

int Car::getSpeed() {           // Lấy tốc độ xe       
	return speed;
}

void Car::setMark(string markIn) {     // Gán nhãn cho xe      
	mark = markIn;
}

string Car::getMark() {           // Lấy nhãn xe      
	return mark;
}
void Car::setPrice(float priceIn) { // Gán giá cho xe      
	price = priceIn;
}
float Car::getPrice() {           // Lấy giá xe    
	return price;
}
/* Khai báo phương thức bên ngoài lớp */
Car::Car(int speed, string mark, float price) {
	this->speed = speed;
	this->mark = mark;
	this->price = price;
}

void Car::show() {                // Phương thức hiển thị xe
	cout << "This is a" << mark << "having a speed of  " << speed << "km/h and its price is $" << price << endl;
	return;
}
/* Định nghĩa lớp Bus kế thừa từ lớp Car */
class Bus : public Car {
	int label;  	 	// Số hiệu tuyến xe  	
public: 
						// Khởi tạo đủ tham số  
	Bus(int speed = 0, string mark = "", float price = 0, int lable = 0);  	 	
	void setLabel(int); 	// Gán số hiệu tuyến xe  	 	
	int getLabel();  	// Đọc số hiệu tuyến xe 
};

// Cài đặt lớp Bus
Bus::Bus(int speed, string mark, float price, int label) :Car(speed, mark, price) {
	this->label = label;
}

void Bus::setLabel(int label) { // Gán số hiệu tuyến xe  	
	this->label = label;
}

int Bus::getLabel() {  	 	// Đọc số hiệu tuyến xe  	
	return this->label; 
}

// Hàm main, chuong trình chính 
int main() {

	Bus myBus;  	 	 	// Biến đối tượng của lớp Bus 
	int speedIn, labelIn; 
	float priceIn; string markIn; 

	// Nhập giá trị cho các thuộc tính
	cout << "Toc do xe bus:";  
	cin >> speedIn; 
	cout << "Nhan hieu xe bus : ";  
	cin >> markIn; 
	cout << "Gia xe bus : ";  
	cin >> priceIn;
	cout << "So hieu tuyen xe bus : ";  
	cin >> labelIn;

	myBus.setSpeed(speedIn); 	// Phương thức của lớp Car 
	myBus.setMark(markIn);  	// Phương thức của lớp Car 
	myBus.setPrice(priceIn); 	// Phương thức của lớp Car 
	myBus.setLabel(labelIn); 	// Phương thức của lớp Bus 
	myBus.show(); 	// Phương thức của lớp Car 
	system("pause");
	return 0;
} 	

Đối tượng myBus có kiểu lớp Bus, là lớp dẫn xuất của lớp cơ sở Car, có thể sử dụng các phương thức của lớp Car và lớp Bus một cách bình đẳng. Khi đó, lệnh myBus.show() sẽ gọi đến phương thức show() của lớp Car, do vậy, chương trình trên sẽ in ra màn hình kết quả như sau 

Kết quả:

Toc do xe bus:120
Nhan hieu xe bus : Toyota
Gia xe bus : 2000
So hieu tuyen xe bus : 9999
This is a Toyota having a speed of  120km/h and its price is $2000

Trong dòng giới thiệu xe bus (vì ta đang dùng đối tượng myBus của lớp Bus), không có giới thiệu số hiệu tuyến xe. Lí do là vì ta đang dùng hàm show của lớp Car. Muốn có thêm phần giới thiệu về số hiệu tuyến xe buýt, ta phải định nghĩa lại hàm show trong lớp Bus.