我试过运行以下代码.请注意,函数“g”调用函数“f”,它在X中是公共的但在Y中是私有的.
class X{
public:
virtual void f(void){cout<<"From X\n";}
virtual void g(X* x) { x->f();}
};
class Y: protected X{
private:
void f(void){cout<<"From Y\n";}
};
int main() {
Y y = Y();
Y *py = &y;
X* px = py;
py->g(py);
return 0;
}
输出是(注意继承受保护):
prog.cpp: In function ‘int main()’:
prog.cpp:18:10: error: ‘X’ is an inaccessible base of ‘Y’
X* px = py;
^
prog.cpp:7:16: error: ‘virtual void X::g(X*)’ is inaccessible
virtual void g(X* x) { x->f();}
^
prog.cpp:19:10: error: within this context
py->g(py);
^
prog.cpp:19:10: error: ‘X’ is not an accessible base of ‘Y’
prog.cpp:19:10: error: ‘X’ is an inaccessible base of ‘Y’
prog.cpp:18:5: warning: unused variable ‘px’ [-Wunused-variable]
X* px = py;
如果我将继承从protected更改为public然后代码工作,我得到以下输出:
From Y
在我看来,当继承是公共的(因为从X调用Y :: f)时,对函数“f”的调用没有强制执行私有访问限制.
在运行这段代码之前,我认为由于访问限制(证明是错误的),我应该总是得到编译时错误.
以某种方式将继承从公共更改为受保护修复此问题并且不启用对Y :: f的调用.
有谁能解释为什么?
解决方法:
封装没有中断:你的方法在X上是公共的,当你使用公共继承时,类Y的对象“也是”类型X的对象.
覆盖C与访问规则正交.您可以使用私有方法覆盖公共方法.这可能是糟糕的设计,因为你总是可以通过对基类的引用来调用它.
这意味着当你有一个指向X的指针时,只适用于类X的访问限制.
请注意,您也可以覆盖私有方法(请参阅“模板方法”GOF设计模式)
class X {
public:
void f () { g (); }
private:
virtual void g () = 0;
};
class Y : public X
{
private:
void g () { std::cout << "from X\n"; }
};
因此,您可能希望尽可能将虚拟功能设置为私有.
至于为什么在使用受保护的继承时它不能编译,这是因为继承受到保护.如果Y从X继承私有或受保护,则无法获得指向X的指针,类型为Y.