本文参考了虚函数的访问控制与多态,在此基础上,通过示例说明了虚函数的重载不受访问控制符的限制,通过指针或者引用可以访问到各个访问控制级别的虚函数。
编译器在决定调用函数时,如果该函数是虚函数才会在运行时确定调用什么函数,如果不是虚函数,那么在编译阶段就已经确定了调用的函数类型。
1. 虚函数的重载不受访问控制符的限制
(1)、 在基类中虚函数是public的,在派生类中可以通过protected、private重载虚函数;
(2) 、在基类中虚函数是private的,在派生类中可以通过protected、public重载虚函数;
2. 通过指针或者引用访问虚函数
(1)、 基类定义虚函数为public,派生类覆盖了该虚函数g(),但是将其声明为protected或private,这样当基类的指针绑定到派生类的对象时,使用该基类指针调用该虚函数时,调用能够成功。
(2)、 基类定义虚函数为private,派生类覆盖了该虚函数f(),但是将其声明为protected或public,这样当基类的指针绑定到派生类的对象时,基类中的友元类,使用该基类指针调用该虚函数时,调用能够成功。
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. 示例输出结果
-------------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