本文參考了虛函數(shù)的訪問控制與多態(tài)檩坚,在此基礎(chǔ)上,通過示例說明了虛函數(shù)的重載不受訪問控制符的限制,通過指針或者引用可以訪問到各個(gè)訪問控制級(jí)別的虛函數(shù)枫浙。
編譯器在決定調(diào)用函數(shù)時(shí),如果該函數(shù)是虛函數(shù)才會(huì)在運(yùn)行時(shí)確定調(diào)用什么函數(shù)古拴,如果不是虛函數(shù)箩帚,那么在編譯階段就已經(jīng)確定了調(diào)用的函數(shù)類型。
1. 虛函數(shù)的重載不受訪問控制符的限制
(1)黄痪、 在基類中虛函數(shù)是public的紧帕,在派生類中可以通過protected、private重載虛函數(shù)桅打;
(2) 是嗜、在基類中虛函數(shù)是private的,在派生類中可以通過protected挺尾、public重載虛函數(shù)鹅搪;
2. 通過指針或者引用訪問虛函數(shù)
(1)、 基類定義虛函數(shù)為public遭铺,派生類覆蓋了該虛函數(shù)g()涩嚣,但是將其聲明為protected或private崇众,這樣當(dāng)基類的指針綁定到派生類的對(duì)象時(shí),使用該基類指針調(diào)用該虛函數(shù)時(shí)航厚,調(diào)用能夠成功顷歌。
(2)、 基類定義虛函數(shù)為private幔睬,派生類覆蓋了該虛函數(shù)f()眯漩,但是將其聲明為protected或public,這樣當(dāng)基類的指針綁定到派生類的對(duì)象時(shí)麻顶,基類中的友元類赦抖,使用該基類指針調(diào)用該虛函數(shù)時(shí),調(diào)用能夠成功辅肾。
3. 示例
/*
* Microsoft Visual Studio 2015
* 2018.04.05
* Written by Xbn
*/
#include <iostream>
using namespace std;
class Base {
friend class Pal;
public:
virtual void g(int i = 0) {
cout << "g(" << i << ") in Base... " << i << endl;
}
protected:
private:
virtual void f(int i = 0) {
cout << "f(" << i << ") in Base... " << i << endl;
}
};
class ProtDerived :public Base {
public:
protected:
void g(int i = 1) override {
cout << "g(" << i << ") in ProtDerived... " << i << endl;
}
void f(int i = 1) override {
cout << "f(" << i << ") in ProtDerived... " << i << endl;
}
private:
};
class PubDerived :public Base {
public:
void f(int i = 2) override {
cout << "f(" << i << ") in PubDerived... " << i << endl;
}
protected:
private:
void g(int i = 2) override {
cout << "g(" << i << ") in PubDerived... " << i << endl;
}
};
class Pal {
public:
void print(Base* b, int i) {
b->f(i);
}
};
int main(void) {
Pal p;
cout << "\n-------------g() is public, f() is private-------------------" << endl;
Base b;
cout << "Direct call public g(): ";
b.g(10);
(&b)->g(10);
p.print(&b, 100);
cout << "\n-------------g() decrease to protected, f() increase to protected-------------------" << endl;
ProtDerived prot;
Base* b1 = &prot;
b1->g(20);
p.print(b1, 200);
cout << "\n-------------g() decrease to private, f() increase to public-------------------" << endl;
PubDerived pub;
cout << "Direct call public f(): ";
pub.f(300);
Base* b2 = &pub;
b2->g(30);
p.print(b2, 300);
return 0;
}
4. 示例輸出結(jié)果
-------------g() is public, f() is private-------------------
Direct call public g(): g(10) in Base... 10
g(10) in Base... 10
f(100) in Base... 100
-------------g() decrease to protected, f() increase to protected-------------------
g(20) in ProtDerived... 20
f(200) in ProtDerived... 200
-------------g() decrease to private, f() increase to public-------------------
Direct call public f(): f(300) in PubDerived... 300
g(30) in PubDerived... 30
f(300) in PubDerived... 300