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.