調整基類成員在派生類中的訪問屬性
一、同名成員
為了在派生類中使用基類的同名成員,必須在該成員名之前加上基類名和作用域識別符號 “ :: ”,格式為:基類名::成員名
派生類可以重新說明與基類成員同名的成員,如果在派生類中定義了與基類成員同名的成員,則稱派生類成員覆蓋了基類的同名成員。
在面向物件程式設計中,若要在派生類中對基類繼承過來的某些函式功能進行擴充和改造,都可以通過這樣的覆蓋來實現。這種覆蓋的方法,是對基類成員改造的關鍵手段,是程式設計中經常使用的方法。
例 1: 同名成員舉例(程式片段)
#include<iostream>
using namespace std;
class X{
public:
int f();
};
class Y:public X{
public:
int f();
int g();
};
void Y::g(){
f(); //訪問派生類中的 f(),即被呼叫的函式是 Y::f(),若要訪問基類中的 f(),應改寫成 X::f()
}
對於派生類的物件的訪問,也有相同的結論,例如,
Y obj;
obj.f(); //被訪問的函式是 Y::f()
如果要訪問基類中宣告的名字,則應使用作用域識別符號限定,例如:
obj.X::f();
例 2:在派生類中定義同名成員
#include<iostream>
#include<string>
using namespace std;
class Student{ //宣告基類 Student
protected:
int num; //學號
string name; //姓名
float score; //成績
public:
Student(int num1,string name1,float score1){ //基類建構函式
num=num1;
name=name1;
score=score1;
}
void print(){
cout<<"number:"<< num<<endl;
cout<<"name:"<<name<<endl;
cout<<"score:"<<score<<endl;
}
};
class Ustudent:private Student{ //宣告私有派生類
private:
string major;
public:
Ustudent(int num1,string name1,float score1,string major1):Student(num1,name1,score1){ //定義派生類建構函式時,綴上基類的建構函式
major=major1;
}
void print(){
Student::print();
cout<<"major:"<<major<<endl;
}
};
int main(){
Ustudent stu(2018,"張值",100,"英語");
stu.print();
return 0;
}
執行結果:
二、訪問宣告
訪問宣告,可個別調整基類的某些成員,使之在派生類中保持原來的訪問屬性。訪問宣告的方法就是把基類的保護成員或公有成員直接寫至私有派生類定義式中的同名段中,同時給成員名前冠以基類名和作用域識別符號“ :: ”,這樣的話,該成員就成為派生類的保護成員或公有成員了。
訪問宣告機制可以在私有派生類中個別調整從基類繼承下來的成員性質,從而使外界可以通過派生類的介面直接訪問基類的某些成員,同時也不影響其他基類成員的封閉性。
例 3:訪問宣告引入的原因
#include<iostream>
using namespace std;
class A{
private:
int x;
public:
A(int x1){
x=x1;
}
void print(){
cout<<"x="<<x;
}
};
class B:private A{
private:
int y;
public:
B(int x1,int y1):A(x1){
y=y1;
}
void print2(){ //通過派生類 B 的函式print2呼叫基類 A 的函式 print
print();
}
};
int main(){
B b(10,20);
b.print2();
return 0;
}
如果將私有派生類 B 中的語句
void print2(){ //通過派生類 B 的函式print2呼叫基類 A 的函式 print
print();
}
改為:
void print(){ A::print(); }
同時將主函式中稍作改變,程式執行結果不變。(用到了一中的同名成員)
但是這種方法在實際應用中卻可能帶來不便,有時程式設計師可能希望 A 的個別成員還能被派生類的物件直接訪問,而不是通過派生類的公有成員函式間接訪問。所以用到了訪問宣告:
class B:private A{
private:
int y;
public:
B(int x1,int y1):A(x1){
y=y1;
}
A::print; //訪問宣告
};
這樣,基類 A 中 print 函式就調整成為派生類 B 的公有成員函式,外界就可以直接呼叫它了。
說明注意:
(1)資料成員也可以使用訪問宣告。
class A{
private:
```
public:
int x2;
```
};
class B:private A{
private:
```
public:
```
A::x2; //把基類中的 x2 調整為派生類的公有成員
```
};
(2)訪問宣告中只含不帶型別和引數的函式名或變數名,即是
A::print;
而不能寫成:
void A::print;
A::print();
void A::print();
(3)訪問宣告不能改變成員在基類中的訪問屬性,即,訪問宣告只能把原基類的保護成員調整為私有派生類的保護成員,把原基類的公有成員調整為私有派生類的公有成員,但對基類的私有成員不能使用訪問宣告。
(4)對於基類中的過載函式名,訪問宣告將對基類中所有同名函式起作用。所以對於過載函式使用訪問宣告要慎重。