子类重写虚函数与在什么访问权限有什么关系?
1.能不能调用 看静态类型
class base
{
private:
virtual void say(){cout<<"base"<<endl;}
};
class child :public base
{
public:
virtual void say(){ cout<<"child"<<endl;}
};
int main()
{
base* a = new child;
a->say();
return 0;
}
这段代码编译会报错, 因为a的静态类型是base,base里say()的权限是private,不能访问
编译期访问检查只基于静态类型,与是否被 override 无关
2.调用了什么 看动态类型
class base
{
public:
virtual void say(){cout<<"base"<<endl;}
};
class child :public base
{
private:
virtual void say() override { cout<<"child"<<endl;}
};
int main()
{
base* a = new child;
a->say();
return 0;
}
这段代码可以运行 输出child
虽然a的动态类型是child 并且child里say的权限是private
但程序依然可以调用并进行动态分发 找到child里的对应函数
3.子类不可以调用父类的private函数
class base
{
public:
void testbase(){say();}
private:
virtual void say(){cout<<"base"<<endl;}
};
class child :public base
{
private:
virtual void say() override { base::say(); cout<<"child"<<endl;}
};
int main()
{
base* a = new child;
a->testbase();
return 0;
}
这段代码错在base::say(),子类不能调用父类的private函数 与是否重写无关
总结:
访问权限只在编译时进行限制,运行期间虚函数的动态分发是不关心访问权限的
注意:
1.父类的private虚函数 可以在子类public下重写
但是子类不能调用父类的版本,
在外部不能通过父类的指针调用该函数
2.子类在private下重写了父类的public函数,
虽然不能用子类的指针调用它自己的函数
依然可以用父类的指针调用子类的版本
使用建议:
访问权限最好在父类就设计好
放在private下的函数 子类只能替换实现 不方便扩展
放在protected下的函数 子类可以很方便地扩展
放在public下的函数 方便外部进行调用